Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Patch] x86, x86_64: Intel HT, Multi core detection code cleanup

35 views
Skip to first unread message

Siddha, Suresh B

unread,
Oct 5, 2005, 7:20:10 PM10/5/05
to
Andrew, Please apply this to your tree. This is 2.6.15 material.

Thanks.
--

This patch cleans up the x86 and x86_64 Intel HT and Multi Core detection code.
These are the areas that this patch touches.

a) Cleanup and merge HT and Mutli Core detection code for x86 and x86_64

b) Fields obtained through cpuid vector 0x1(ebx[16:23]) and
vector 0x4(eax[14:25], eax[26:31]) indicate the maximum values and might not
always be the same as what is available and what OS sees. So make sure
"siblings" and "cpu cores" values in /proc/cpuinfo reflect the values as seen
by OS instead of what cpuid instruction says. This will also fix the buggy BIOS
cases (for example where cpuid on a single core cpu says there are "2" siblings,
even when HT is disabled in the BIOS. http://bugzilla.kernel.org/show_bug.cgi?id=4359)

c) Fix the cache detection code assumption that number of threads sharing the
cache will either be equal to number of HT or core siblings.

Signed-off-by: Suresh Siddha <suresh....@intel.com>

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/Makefile linux-2.6.14-rc3-core/arch/i386/kernel/Makefile
--- linux-2.6.14-rc3/arch/i386/kernel/Makefile 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/i386/kernel/Makefile 2005-10-04 17:27:28.436096192 -0700
@@ -18,7 +18,7 @@ obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_APM) += apm.o
-obj-$(CONFIG_X86_SMP) += smp.o smpboot.o
+obj-$(CONFIG_X86_SMP) += smp.o smpboot.o sibling-map.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/Makefile linux-2.6.14-rc3-core/arch/i386/kernel/cpu/Makefile
--- linux-2.6.14-rc3/arch/i386/kernel/cpu/Makefile 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/i386/kernel/cpu/Makefile 2005-10-04 17:27:28.436096192 -0700
@@ -8,7 +8,7 @@ obj-y += amd.o
obj-y += cyrix.o
obj-y += centaur.o
obj-y += transmeta.o
-obj-y += intel.o intel_cacheinfo.o
+obj-y += intel.o intel_cacheinfo.o intel_htmc.o
obj-y += rise.o
obj-y += nexgen.o
obj-y += umc.o
diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/common.c linux-2.6.14-rc3-core/arch/i386/kernel/cpu/common.c
--- linux-2.6.14-rc3/arch/i386/kernel/cpu/common.c 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/i386/kernel/cpu/common.c 2005-10-04 17:27:28.437096040 -0700
@@ -442,61 +442,6 @@ void __devinit identify_cpu(struct cpuin
mtrr_ap_init();
}

-#ifdef CONFIG_X86_HT
-void __devinit detect_ht(struct cpuinfo_x86 *c)
-{
- u32 eax, ebx, ecx, edx;
- int index_msb, tmp;
- int cpu = smp_processor_id();
-
- if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
- return;
-
- cpuid(1, &eax, &ebx, &ecx, &edx);
- smp_num_siblings = (ebx & 0xff0000) >> 16;
-
- if (smp_num_siblings == 1) {
- printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
- } else if (smp_num_siblings > 1 ) {
- index_msb = 31;
-
- if (smp_num_siblings > NR_CPUS) {
- printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
- smp_num_siblings = 1;
- return;
- }
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- 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

void __devinit print_cpu_info(struct cpuinfo_x86 *c)
{
diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel.c linux-2.6.14-rc3-core/arch/i386/kernel/cpu/intel.c
--- linux-2.6.14-rc3/arch/i386/kernel/cpu/intel.c 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/i386/kernel/cpu/intel.c 2005-10-04 17:27:28.437096040 -0700
@@ -76,25 +76,6 @@ static void __devinit Intel_errata_worka
}
}

-
-/*
- * find out the number of processor cores on the die
- */
-static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
-{
- unsigned int eax, ebx, ecx, edx;
-
- if (c->cpuid_level < 4)
- return 1;
-
- /* Intel has a non-standard dependency on %ecx for this CPUID level. */
- cpuid_count(4, 0, &eax, &ebx, &ecx, &edx);
- if (eax & 0x1f)
- return ((eax >> 26) + 1);
- else
- return 1;
-}
-
static void __devinit init_intel(struct cpuinfo_x86 *c)
{
unsigned int l2 = 0;
@@ -157,7 +138,7 @@ static void __devinit init_intel(struct
if ( p )
strcpy(c->x86_model_id, p);

- c->x86_num_cores = num_cpu_cores(c);
+ c->x86_num_cores = intel_num_cpu_cores(c);

detect_ht(c);

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_cacheinfo.c linux-2.6.14-rc3-core/arch/i386/kernel/cpu/intel_cacheinfo.c
--- linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-10-04 17:27:28.438095888 -0700
@@ -303,29 +303,45 @@ static struct _cpuid4_info *cpuid4_info[
#ifdef CONFIG_SMP
static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
{
- struct _cpuid4_info *this_leaf;
+ struct _cpuid4_info *this_leaf, *sibling_leaf;
unsigned long num_threads_sharing;
-#ifdef CONFIG_X86_HT
- struct cpuinfo_x86 *c = cpu_data + cpu;
-#endif
+ int index_msb, i;
+ struct cpuinfo_x86 *c = cpu_data;

this_leaf = CPUID4_INFO_IDX(cpu, index);
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;

if (num_threads_sharing == 1)
cpu_set(cpu, this_leaf->shared_cpu_map);
-#ifdef CONFIG_X86_HT
- else if (num_threads_sharing == smp_num_siblings)
- this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
- else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings))
- this_leaf->shared_cpu_map = cpu_core_map[cpu];
- else
- printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "
- "any known set of CPUs\n");
-#endif
+ else {
+ index_msb = get_count_order(num_threads_sharing);
+
+ for_each_online_cpu(i) {
+ if (c[i].apicid >> index_msb ==
+ c[cpu].apicid >> index_msb) {
+ cpu_set(i, this_leaf->shared_cpu_map);
+ if (i != cpu && cpuid4_info[i]) {
+ sibling_leaf = CPUID4_INFO_IDX(i, index);
+ cpu_set(cpu, sibling_leaf->shared_cpu_map);
+ }
+ }
+ }
+ }
+}
+static void __devinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
+{
+ struct _cpuid4_info *this_leaf, *sibling_leaf;
+ int sibling;
+
+ this_leaf = CPUID4_INFO_IDX(cpu, index);
+ for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) {
+ sibling_leaf = CPUID4_INFO_IDX(sibling, index);
+ cpu_clear(cpu, sibling_leaf->shared_cpu_map);
+ }
}
#else
static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
+static void __init cache_remove_shared_cpu_map(unsigned int cpu, int index) {}
#endif

static void free_cache_attributes(unsigned int cpu)
@@ -584,8 +600,10 @@ static int __devexit cache_remove_dev(st
unsigned int cpu = sys_dev->id;
unsigned long i;

- for (i = 0; i < num_cache_leaves; i++)
+ for (i = 0; i < num_cache_leaves; i++) {
+ cache_remove_shared_cpu_map(cpu, i);
kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+ }
kobject_unregister(cache_kobject[cpu]);
cpuid4_cache_sysfs_exit(cpu);
return 0;
diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_htmc.c linux-2.6.14-rc3-core/arch/i386/kernel/cpu/intel_htmc.c
--- linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_htmc.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.14-rc3-core/arch/i386/kernel/cpu/intel_htmc.c 2005-10-04 17:27:28.438095888 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2005 Intel Corp
+ * Intel Multi Core and Hyper-Threading detection routines
+ *
+ * Changes:
+ * Suresh Siddha : Merge x86 and x86_64 code with some fixes.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/smp.h>
+#include <asm/processor.h>
+
+
+/*
+ * find out the number of processor cores on the die
+ */
+int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (c->cpuid_level < 4)
+ return 1;
+
+ cpuid_count(4, 0, &eax, &ebx, &ecx, &edx);
+
+ if (eax & 0x1f)
+ return ((eax >> 26) + 1);
+ else
+ return 1;
+}
+
+#ifdef CONFIG_X86_HT
+#ifndef CONFIG_X86_64
+#include <mach_apic.h>
+#else
+#include <asm/mach_apic.h>
+#endif
+void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+{
+ u32 eax, ebx, ecx, edx;
+ int index_msb, core_bits;
+ int cpu = smp_processor_id();
+
+ cpuid(1, &eax, &ebx, &ecx, &edx);
+#ifdef CONFIG_X86_64
+ c->apicid = phys_pkg_id(0);
+#else
+ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
+#endif
+
+ if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
+ return;
+
+ smp_num_siblings = (ebx & 0xff0000) >> 16;
+
+ if (smp_num_siblings == 1) {
+ printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
+ } else if (smp_num_siblings > 1 ) {
+
+ if (smp_num_siblings > NR_CPUS) {
+ printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
+ smp_num_siblings = 1;
+ return;
+ }
+
+ index_msb = get_count_order(smp_num_siblings);
+#ifdef CONFIG_X86_64
+ phys_proc_id[cpu] = phys_pkg_id(index_msb);
+#else
+ phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
+#endif
+
+ printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
+ phys_proc_id[cpu]);
+
+ smp_num_siblings = smp_num_siblings / c->x86_num_cores;
+
+ index_msb = get_count_order(smp_num_siblings) ;
+
+ core_bits = get_count_order(c->x86_num_cores);
+
+#ifdef CONFIG_X86_64
+ cpu_core_id[cpu] = phys_pkg_id(index_msb) &
+ ((1 << core_bits) - 1);
+#else
+ cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
+ ((1 << core_bits) - 1);
+#endif
+
+ if (c->x86_num_cores > 1)
+ printk(KERN_INFO "CPU: Processor Core ID: %d\n",
+ cpu_core_id[cpu]);
+ }
+}
+#endif
diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/proc.c linux-2.6.14-rc3-core/arch/i386/kernel/cpu/proc.c
--- linux-2.6.14-rc3/arch/i386/kernel/cpu/proc.c 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/i386/kernel/cpu/proc.c 2005-10-04 17:27:28.439095736 -0700
@@ -97,9 +97,9 @@ static int show_cpuinfo(struct seq_file
if (c->x86_num_cores * smp_num_siblings > 1) {
seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
seq_printf(m, "siblings\t: %d\n",
- c->x86_num_cores * smp_num_siblings);
+ cpus_weight(cpu_core_map[n]));
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);
+ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
#endif

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/sibling-map.c linux-2.6.14-rc3-core/arch/i386/kernel/sibling-map.c
--- linux-2.6.14-rc3/arch/i386/kernel/sibling-map.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.14-rc3-core/arch/i386/kernel/sibling-map.c 2005-10-04 17:27:28.439095736 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2005 Intel Corp
+ * Setup and Removal of various sibling maps
+ *
+ * Changes:
+ * Suresh Siddha : Merge x86 and x86_64 code with some fixes
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/smp.h>
+
+static cpumask_t cpu_sibling_setup_map;
+
+#ifdef CONFIG_HOTPLUG_CPU
+void
+remove_siblinginfo(int cpu)
+{
+ int sibling;
+ struct cpuinfo_x86 *c = cpu_data;
+
+ for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
+ cpu_clear(cpu, cpu_core_map[sibling]);
+ /*
+ * last thread sibling in this cpu core going down
+ */
+ if (cpus_weight(cpu_sibling_map[cpu]) == 1)
+ c[sibling].booted_cores--;
+ }
+
+ for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
+ cpu_clear(cpu, cpu_sibling_map[sibling]);
+ cpus_clear(cpu_sibling_map[cpu]);
+ cpus_clear(cpu_core_map[cpu]);
+ phys_proc_id[cpu] = BAD_APICID;
+ cpu_core_id[cpu] = BAD_APICID;
+ cpu_clear(cpu, cpu_sibling_setup_map);
+}
+#endif
+
+void __cpuinit
+set_cpu_sibling_map(int cpu)
+{
+ int i;
+ struct cpuinfo_x86 *c = cpu_data;
+
+ cpu_set(cpu, cpu_sibling_setup_map);
+
+ if (smp_num_siblings > 1) {
+ for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (phys_proc_id[cpu] == phys_proc_id[i] &&
+ cpu_core_id[cpu] == cpu_core_id[i]) {
+ cpu_set(i, cpu_sibling_map[cpu]);
+ cpu_set(cpu, cpu_sibling_map[i]);
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
+ }
+ }
+ } else {
+ cpu_set(cpu, cpu_sibling_map[cpu]);
+ }
+
+ if (current_cpu_data.x86_num_cores == 1) {
+ cpu_core_map[cpu] = cpu_sibling_map[cpu];
+ c[cpu].booted_cores = 1;
+ return;
+ }
+
+ for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (phys_proc_id[cpu] == phys_proc_id[i]) {
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
+ /*
+ * Does this new cpu bringup a new core?
+ */
+ if (cpus_weight(cpu_sibling_map[cpu]) == 1) {
+ /*
+ * for each core in package, increment
+ * the booted_cores for this new cpu
+ */
+ if (first_cpu(cpu_sibling_map[i]) == i)
+ c[cpu].booted_cores++;
+ /*
+ * increment the core count for all
+ * the other cpus in this package
+ */
+ if (i != cpu)
+ c[i].booted_cores++;
+ } else if (i != cpu && !c[cpu].booted_cores)
+ c[cpu].booted_cores = c[i].booted_cores;
+ }
+ }
+}
diff -pNru linux-2.6.14-rc3/arch/i386/kernel/smpboot.c linux-2.6.14-rc3-core/arch/i386/kernel/smpboot.c
--- linux-2.6.14-rc3/arch/i386/kernel/smpboot.c 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/i386/kernel/smpboot.c 2005-10-05 15:23:37.137028880 -0700
@@ -440,38 +440,6 @@ static void __devinit smp_callin(void)

static int cpucount;

-static inline void
-set_cpu_sibling_map(int cpu)
-{
- int i;
-
- if (smp_num_siblings > 1) {
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_isset(i, cpu_callout_map))
- continue;
- if (cpu_core_id[cpu] == cpu_core_id[i]) {
- cpu_set(i, cpu_sibling_map[cpu]);
- cpu_set(cpu, cpu_sibling_map[i]);
- }
- }
- } else {
- cpu_set(cpu, cpu_sibling_map[cpu]);
- }
-
- if (current_cpu_data.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]);
- cpu_set(cpu, cpu_core_map[i]);
- }
- }
- } else {
- cpu_core_map[cpu] = cpu_sibling_map[cpu];
- }
-}
-
/*
* Activate a secondary processor.
*/
@@ -1092,11 +1060,7 @@ static void __init smp_boot_cpus(unsigne

current_thread_info()->cpu = 0;
smp_tune_scheduling();
- 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]);
+ set_cpu_sibling_map(raw_smp_processor_id());

/*
* If we couldn't find an SMP configuration at boot time,
@@ -1271,21 +1235,6 @@ void __devinit smp_prepare_boot_cpu(void
}

#ifdef CONFIG_HOTPLUG_CPU
-static void
-remove_siblinginfo(int cpu)
-{
- int sibling;
-
- for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
- cpu_clear(cpu, cpu_sibling_map[sibling]);
- for_each_cpu_mask(sibling, cpu_core_map[cpu])
- cpu_clear(cpu, cpu_core_map[sibling]);
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
- phys_proc_id[cpu] = BAD_APICID;
- cpu_core_id[cpu] = BAD_APICID;
-}
-
int __cpu_disable(void)
{
cpumask_t map = cpu_online_map;
diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/Makefile linux-2.6.14-rc3-core/arch/x86_64/kernel/Makefile
--- linux-2.6.14-rc3/arch/x86_64/kernel/Makefile 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/x86_64/kernel/Makefile 2005-10-04 17:27:28.440095584 -0700
@@ -16,7 +16,7 @@ obj-$(CONFIG_ACPI) += acpi/
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
-obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
+obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o sibling-map.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \
genapic.o genapic_cluster.o genapic_flat.o
@@ -34,7 +34,7 @@ obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
obj-$(CONFIG_MODULES) += module.o

obj-y += topology.o
-obj-y += intel_cacheinfo.o
+obj-y += intel_cacheinfo.o intel_htmc.o

CFLAGS_vsyscall.o := $(PROFILING) -g0

@@ -47,3 +47,5 @@ intel_cacheinfo-y += ../../i386/kernel/
quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
+sibling-map-y += ../../i386/kernel/sibling-map.o
+intel_htmc-y += ../../i386/kernel/cpu/intel_htmc.o
diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/setup.c linux-2.6.14-rc3-core/arch/x86_64/kernel/setup.c
--- linux-2.6.14-rc3/arch/x86_64/kernel/setup.c 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/x86_64/kernel/setup.c 2005-10-04 17:27:28.441095432 -0700
@@ -885,85 +885,6 @@ static int __init init_amd(struct cpuinf
return r;
}

-static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
-{
-#ifdef CONFIG_SMP
- u32 eax, ebx, ecx, edx;
- int index_msb, tmp;
- int cpu = smp_processor_id();
-
- if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
- return;
-
- cpuid(1, &eax, &ebx, &ecx, &edx);
- smp_num_siblings = (ebx & 0xff0000) >> 16;
-
- if (smp_num_siblings == 1) {
- printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
- } else if (smp_num_siblings > 1) {
- index_msb = 31;
- /*
- * At this point we only support two siblings per
- * processor package.
- */
- if (smp_num_siblings > NR_CPUS) {
- printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
- smp_num_siblings = 1;
- return;
- }
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- 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
-}
-
-/*
- * find out the number of processor cores on the die
- */
-static int __cpuinit 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 srat_detect_node(void)
{
#ifdef CONFIG_NUMA
@@ -1276,9 +1197,9 @@ static int show_cpuinfo(struct seq_file
int cpu = c - cpu_data;
seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);
seq_printf(m, "siblings\t: %d\n",
- c->x86_num_cores * smp_num_siblings);
+ cpus_weight(cpu_core_map[cpu]));
seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]);
- seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
+ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
#endif

diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/smpboot.c linux-2.6.14-rc3-core/arch/x86_64/kernel/smpboot.c
--- linux-2.6.14-rc3/arch/x86_64/kernel/smpboot.c 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/arch/x86_64/kernel/smpboot.c 2005-10-04 17:27:28.442095280 -0700
@@ -436,33 +436,6 @@ void __cpuinit smp_callin(void)
cpu_set(cpuid, cpu_callin_map);
}

-static inline void set_cpu_sibling_map(int cpu)
-{
- int i;
-
- if (smp_num_siblings > 1) {
- for_each_cpu(i) {
- if (cpu_core_id[cpu] == cpu_core_id[i]) {
- cpu_set(i, cpu_sibling_map[cpu]);
- cpu_set(cpu, cpu_sibling_map[i]);
- }
- }
- } else {
- cpu_set(cpu, cpu_sibling_map[cpu]);
- }
-
- if (current_cpu_data.x86_num_cores > 1) {
- for_each_cpu(i) {
- if (phys_proc_id[cpu] == phys_proc_id[i]) {
- cpu_set(i, cpu_core_map[cpu]);
- cpu_set(cpu, cpu_core_map[i]);
- }
- }
- } else {
- cpu_core_map[cpu] = cpu_sibling_map[cpu];
- }
-}
-
/*
* Setup code on secondary processor (after comming out of the trampoline)
*/
@@ -966,6 +939,7 @@ void __init smp_prepare_cpus(unsigned in
nmi_watchdog_default();
current_cpu_data = boot_cpu_data;
current_thread_info()->cpu = 0; /* needed? */
+ set_cpu_sibling_map(0);

#ifdef CONFIG_HOTPLUG_CPU
prefill_possible_map();
@@ -1013,8 +987,7 @@ void __init smp_prepare_boot_cpu(void)
int me = smp_processor_id();
cpu_set(me, cpu_online_map);
cpu_set(me, cpu_callout_map);
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
+
per_cpu(cpu_state, me) = CPU_ONLINE;
}

@@ -1083,20 +1056,6 @@ void __init smp_cpus_done(unsigned int m

#ifdef CONFIG_HOTPLUG_CPU

-static void remove_siblinginfo(int cpu)
-{
- int sibling;
-
- for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
- cpu_clear(cpu, cpu_sibling_map[sibling]);
- for_each_cpu_mask(sibling, cpu_core_map[cpu])
- cpu_clear(cpu, cpu_core_map[sibling]);
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
- phys_proc_id[cpu] = BAD_APICID;
- cpu_core_id[cpu] = BAD_APICID;
-}
-
void remove_cpu_from_maps(void)
{
int cpu = smp_processor_id();
diff -pNru linux-2.6.14-rc3/include/asm-i386/processor.h linux-2.6.14-rc3-core/include/asm-i386/processor.h
--- linux-2.6.14-rc3/include/asm-i386/processor.h 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/include/asm-i386/processor.h 2005-10-04 17:27:28.443095128 -0700
@@ -66,6 +66,8 @@ struct cpuinfo_x86 {
int coma_bug;
unsigned long loops_per_jiffy;
unsigned char x86_num_cores;
+ unsigned char booted_cores;
+ unsigned char apicid;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));

#define X86_VENDOR_INTEL 0
@@ -104,6 +106,7 @@ extern char ignore_fpu_irq;
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+extern int intel_num_cpu_cores(struct cpuinfo_x86 *c);

#ifdef CONFIG_X86_HT
extern void detect_ht(struct cpuinfo_x86 *c);
diff -pNru linux-2.6.14-rc3/include/asm-i386/smp.h linux-2.6.14-rc3-core/include/asm-i386/smp.h
--- linux-2.6.14-rc3/include/asm-i386/smp.h 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/include/asm-i386/smp.h 2005-10-05 15:24:59.695478088 -0700
@@ -37,6 +37,9 @@ extern int smp_num_siblings;
extern cpumask_t cpu_sibling_map[];
extern cpumask_t cpu_core_map[];

+extern void set_cpu_sibling_map(int);
+extern void remove_siblinginfo(int);
+
extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void);
extern void lock_ipi_call_lock(void);
diff -pNru linux-2.6.14-rc3/include/asm-x86_64/processor.h linux-2.6.14-rc3-core/include/asm-x86_64/processor.h
--- linux-2.6.14-rc3/include/asm-x86_64/processor.h 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/include/asm-x86_64/processor.h 2005-10-04 17:27:28.443095128 -0700
@@ -65,6 +65,8 @@ struct cpuinfo_x86 {
__u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy;
+ __u8 apicid;
+ __u8 booted_cores;
} ____cacheline_aligned;

#define X86_VENDOR_INTEL 0
@@ -91,6 +93,14 @@ extern char ignore_irq13;
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+extern int intel_num_cpu_cores(struct cpuinfo_x86 *c);
+
+#ifdef CONFIG_X86_HT
+extern void detect_ht(struct cpuinfo_x86 *c);
+#else
+static inline void detect_ht(struct cpuinfo_x86 *c) {}
+#endif
+

/*
* EFLAGS bits
diff -pNru linux-2.6.14-rc3/include/asm-x86_64/smp.h linux-2.6.14-rc3-core/include/asm-x86_64/smp.h
--- linux-2.6.14-rc3/include/asm-x86_64/smp.h 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/include/asm-x86_64/smp.h 2005-10-04 17:27:28.444094976 -0700
@@ -57,6 +57,9 @@ extern cpumask_t cpu_core_map[NR_CPUS];
extern u8 phys_proc_id[NR_CPUS];
extern u8 cpu_core_id[NR_CPUS];

+extern void set_cpu_sibling_map(int);
+extern void remove_siblinginfo(int);
+
#define SMP_TRAMPOLINE_BASE 0x6000

/*
diff -pNru linux-2.6.14-rc3/include/linux/bitops.h linux-2.6.14-rc3-core/include/linux/bitops.h
--- linux-2.6.14-rc3/include/linux/bitops.h 2005-09-30 14:17:35.000000000 -0700
+++ linux-2.6.14-rc3-core/include/linux/bitops.h 2005-10-04 17:27:28.444094976 -0700
@@ -84,6 +84,16 @@ static __inline__ int get_bitmask_order(
return order; /* We could be slightly more clever with -1 here... */
}

+static __inline__ int get_count_order(unsigned int count)
+{
+ int order;
+
+ order = fls(count) - 1;
+ if (count & (count - 1))
+ order++;
+ return order;
+}
+
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Andi Kleen

unread,
Oct 6, 2005, 6:50:40 AM10/6/05
to
On Thursday 06 October 2005 01:17, Siddha, Suresh B wrote:

> +
> +#ifdef CONFIG_X86_HT
> +#ifndef CONFIG_X86_64
> +#include <mach_apic.h>
> +#else
> +#include <asm/mach_apic.h>
> +#endif

Having such ifdefs is a clear cue that the code shouldn't be shared
between architectures.

-Andi

Siddha, Suresh B

unread,
Oct 6, 2005, 10:30:15 PM10/6/05
to
On Thu, Oct 06, 2005 at 12:42:25PM +0200, Andi Kleen wrote:
> On Thursday 06 October 2005 01:17, Siddha, Suresh B wrote:
>
> > +
> > +#ifdef CONFIG_X86_HT
> > +#ifndef CONFIG_X86_64
> > +#include <mach_apic.h>
> > +#else
> > +#include <asm/mach_apic.h>
> > +#endif
>
> Having such ifdefs is a clear cue that the code shouldn't be shared
> between architectures.

Andi, Those headers are for phys_pkg_id(). And its meaning is same on both
x86 and x86_64(though its API is different. We can make it consistent across
x86 and x86_64. But that will not solve the above pointed out ifdef hunk)

Unfortunately x86 mach specific vector implementation is not as simple as
x86_64, resulting in the above ifdefs mess...

I can fix the API mess. Is there anything else you want me to do?

thanks,
suresh

Andi Kleen

unread,
Oct 7, 2005, 6:00:22 AM10/7/05
to
> I can fix the API mess. Is there anything else you want me to do?

I think you overdid the sharing. Can you limit it to one file
and copy the stuff that doesn't fit easily?

-Andi

Siddha, Suresh B

unread,
Oct 7, 2005, 9:00:11 PM10/7/05
to
On Fri, Oct 07, 2005 at 11:52:00AM +0200, Andi Kleen wrote:
> > I can fix the API mess. Is there anything else you want me to do?
>
> I think you overdid the sharing. Can you limit it to one file
> and copy the stuff that doesn't fit easily?

Andi, This stuff is very much common to x86 and x86_64. Shared code is split
into two files because setting up sibling map code is generic and HT/core
detection code is very specific to Intel.

How about the appended patch?

thanks,
suresh
--

This patch cleans up the Intel HT and Multi Core detection code in x86
and x86_64. These are the areas that this patch touches.

a) Cleanup and merge HT and Mutli Core detection code for x86 and x86_64

b) Fields obtained through cpuid vector 0x1(ebx[16:23]) and
vector 0x4(eax[14:25], eax[26:31]) indicate the maximum values and might not
always be the same as what is available and what OS sees. So make sure
"siblings" and "cpu cores" values in /proc/cpuinfo reflect the values as seen
by OS instead of what cpuid instruction says. This will also fix the buggy BIOS

cases (for example where cpuid says there are "2" siblings, even when HT is

c) Fix the cache detection code assumption that number of threads sharing the
cache will either be equal to number of HT or core siblings.

Signed-off-by: Suresh Siddha <suresh....@intel.com>

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile


--- linux-2.6.14-rc3/arch/i386/kernel/Makefile 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/Makefile 2005-10-07 16:27:37.706580584 -0700


@@ -18,7 +18,7 @@ obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_APM) += apm.o
-obj-$(CONFIG_X86_SMP) += smp.o smpboot.o
+obj-$(CONFIG_X86_SMP) += smp.o smpboot.o sibling-map.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/Makefile linux/arch/i386/kernel/cpu/Makefile


--- linux-2.6.14-rc3/arch/i386/kernel/cpu/Makefile 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/cpu/Makefile 2005-10-07 16:27:37.706580584 -0700


@@ -8,7 +8,7 @@ obj-y += amd.o
obj-y += cyrix.o
obj-y += centaur.o
obj-y += transmeta.o
-obj-y += intel.o intel_cacheinfo.o
+obj-y += intel.o intel_cacheinfo.o intel_htmc.o
obj-y += rise.o
obj-y += nexgen.o
obj-y += umc.o

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/common.c linux/arch/i386/kernel/cpu/common.c


--- linux-2.6.14-rc3/arch/i386/kernel/cpu/common.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/cpu/common.c 2005-10-07 16:27:37.707580432 -0700

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel.c linux/arch/i386/kernel/cpu/intel.c


--- linux-2.6.14-rc3/arch/i386/kernel/cpu/intel.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/cpu/intel.c 2005-10-07 16:27:37.707580432 -0700

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_cacheinfo.c linux/arch/i386/kernel/cpu/intel_cacheinfo.c


--- linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-10-07 16:27:37.708580280 -0700

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_htmc.c linux/arch/i386/kernel/cpu/intel_htmc.c


--- linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_htmc.c 1969-12-31 16:00:00.000000000 -0800

+++ linux/arch/i386/kernel/cpu/intel_htmc.c 2005-10-07 16:27:37.708580280 -0700
@@ -0,0 +1,81 @@

+#include <asm/mach_apic.h>
+


+void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+{
+ u32 eax, ebx, ecx, edx;
+ int index_msb, core_bits;
+ int cpu = smp_processor_id();
+
+ cpuid(1, &eax, &ebx, &ecx, &edx);
+

+ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);

+
+ if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
+ return;
+
+ smp_num_siblings = (ebx & 0xff0000) >> 16;
+
+ if (smp_num_siblings == 1) {
+ printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
+ } else if (smp_num_siblings > 1 ) {
+
+ if (smp_num_siblings > NR_CPUS) {
+ printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
+ smp_num_siblings = 1;
+ return;
+ }
+
+ index_msb = get_count_order(smp_num_siblings);

+ 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;
+
+ index_msb = get_count_order(smp_num_siblings) ;
+
+ core_bits = get_count_order(c->x86_num_cores);
+

+ cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
+ ((1 << core_bits) - 1);

+
+ if (c->x86_num_cores > 1)
+ printk(KERN_INFO "CPU: Processor Core ID: %d\n",
+ cpu_core_id[cpu]);
+ }
+}
+#endif

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/proc.c linux/arch/i386/kernel/cpu/proc.c


--- linux-2.6.14-rc3/arch/i386/kernel/cpu/proc.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/cpu/proc.c 2005-10-07 16:27:37.709580128 -0700


@@ -97,9 +97,9 @@ static int show_cpuinfo(struct seq_file
if (c->x86_num_cores * smp_num_siblings > 1) {
seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
seq_printf(m, "siblings\t: %d\n",
- c->x86_num_cores * smp_num_siblings);
+ cpus_weight(cpu_core_map[n]));
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);
+ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
#endif

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/sibling-map.c linux/arch/i386/kernel/sibling-map.c


--- linux-2.6.14-rc3/arch/i386/kernel/sibling-map.c 1969-12-31 16:00:00.000000000 -0800

+++ linux/arch/i386/kernel/sibling-map.c 2005-10-07 16:27:37.709580128 -0700

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c


--- linux-2.6.14-rc3/arch/i386/kernel/smpboot.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/smpboot.c 2005-10-07 16:27:37.710579976 -0700

diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/Makefile linux/arch/x86_64/kernel/Makefile


--- linux-2.6.14-rc3/arch/x86_64/kernel/Makefile 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/x86_64/kernel/Makefile 2005-10-07 16:27:37.710579976 -0700


@@ -16,7 +16,7 @@ obj-$(CONFIG_ACPI) += acpi/
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
-obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
+obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o sibling-map.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \
genapic.o genapic_cluster.o genapic_flat.o
@@ -34,7 +34,7 @@ obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
obj-$(CONFIG_MODULES) += module.o

obj-y += topology.o
-obj-y += intel_cacheinfo.o
+obj-y += intel_cacheinfo.o intel_htmc.o

CFLAGS_vsyscall.o := $(PROFILING) -g0

@@ -47,3 +47,5 @@ intel_cacheinfo-y += ../../i386/kernel/
quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
+sibling-map-y += ../../i386/kernel/sibling-map.o
+intel_htmc-y += ../../i386/kernel/cpu/intel_htmc.o

diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/genapic_cluster.c linux/arch/x86_64/kernel/genapic_cluster.c
--- linux-2.6.14-rc3/arch/x86_64/kernel/genapic_cluster.c 2005-09-30 14:17:35.000000000 -0700
+++ linux/arch/x86_64/kernel/genapic_cluster.c 2005-10-07 16:29:23.157549600 -0700
@@ -113,7 +113,7 @@ static unsigned int cluster_cpu_mask_to_
*
* See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
*/
-static unsigned int phys_pkg_id(int index_msb)
+static unsigned int phys_pkg_id(u32 cpu_apicid, int index_msb)
{
return hard_smp_processor_id() >> index_msb;
}
diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/genapic_flat.c linux/arch/x86_64/kernel/genapic_flat.c
--- linux-2.6.14-rc3/arch/x86_64/kernel/genapic_flat.c 2005-09-30 14:17:35.000000000 -0700
+++ linux/arch/x86_64/kernel/genapic_flat.c 2005-10-07 16:29:42.509607640 -0700
@@ -107,12 +107,9 @@ static unsigned int flat_cpu_mask_to_api
return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
}

-static unsigned int phys_pkg_id(int index_msb)
+static unsigned int phys_pkg_id(u32 cpu_apicid, int index_msb)
{
- u32 ebx;
-
- ebx = cpuid_ebx(1);
- return ((ebx >> 24) & 0xFF) >> index_msb;
+ return cpu_apicid >> index_msb;
}

struct genapic apic_flat = {
diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/setup.c linux/arch/x86_64/kernel/setup.c


--- linux-2.6.14-rc3/arch/x86_64/kernel/setup.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/x86_64/kernel/setup.c 2005-10-07 16:27:37.711579824 -0700

diff -pNru linux-2.6.14-rc3/arch/x86_64/kernel/smpboot.c linux/arch/x86_64/kernel/smpboot.c


--- linux-2.6.14-rc3/arch/x86_64/kernel/smpboot.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/x86_64/kernel/smpboot.c 2005-10-07 16:27:37.712579672 -0700

diff -pNru linux-2.6.14-rc3/include/asm-i386/mach_apic.h linux/include/asm-i386/mach_apic.h
--- linux-2.6.14-rc3/include/asm-i386/mach_apic.h 1969-12-31 16:00:00.000000000 -0800
+++ linux/include/asm-i386/mach_apic.h 2005-10-07 16:27:37.712579672 -0700
@@ -0,0 +1,5 @@
+/* Magic for including machine specific mach_apic.h from C files,
+ * so that shared code between i386 and x86_64 can simply include
+ * <asm/mach_apic.h> without complicated ifdefs
+ */
+#include <mach_apic.h>
diff -pNru linux-2.6.14-rc3/include/asm-i386/processor.h linux/include/asm-i386/processor.h


--- linux-2.6.14-rc3/include/asm-i386/processor.h 2005-09-30 14:17:35.000000000 -0700

+++ linux/include/asm-i386/processor.h 2005-10-07 16:27:37.713579520 -0700


@@ -66,6 +66,8 @@ struct cpuinfo_x86 {
int coma_bug;
unsigned long loops_per_jiffy;
unsigned char x86_num_cores;
+ unsigned char booted_cores;
+ unsigned char apicid;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));

#define X86_VENDOR_INTEL 0
@@ -104,6 +106,7 @@ extern char ignore_fpu_irq;
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+extern int intel_num_cpu_cores(struct cpuinfo_x86 *c);

#ifdef CONFIG_X86_HT
extern void detect_ht(struct cpuinfo_x86 *c);

diff -pNru linux-2.6.14-rc3/include/asm-i386/smp.h linux/include/asm-i386/smp.h


--- linux-2.6.14-rc3/include/asm-i386/smp.h 2005-09-30 14:17:35.000000000 -0700

+++ linux/include/asm-i386/smp.h 2005-10-07 16:27:37.713579520 -0700


@@ -37,6 +37,9 @@ extern int smp_num_siblings;
extern cpumask_t cpu_sibling_map[];
extern cpumask_t cpu_core_map[];

+extern void set_cpu_sibling_map(int);
+extern void remove_siblinginfo(int);
+
extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void);
extern void lock_ipi_call_lock(void);

diff -pNru linux-2.6.14-rc3/include/asm-x86_64/genapic.h linux/include/asm-x86_64/genapic.h
--- linux-2.6.14-rc3/include/asm-x86_64/genapic.h 2005-09-30 14:17:35.000000000 -0700
+++ linux/include/asm-x86_64/genapic.h 2005-10-07 16:30:02.322595608 -0700
@@ -26,7 +26,7 @@ struct genapic {
void (*send_IPI_all)(int vector);
/* */
unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
- unsigned int (*phys_pkg_id)(int index_msb);
+ unsigned int (*phys_pkg_id)(u32 cpu_apicid, int index_msb);
};


diff -pNru linux-2.6.14-rc3/include/asm-x86_64/processor.h linux/include/asm-x86_64/processor.h


--- linux-2.6.14-rc3/include/asm-x86_64/processor.h 2005-09-30 14:17:35.000000000 -0700

+++ linux/include/asm-x86_64/processor.h 2005-10-07 16:27:37.713579520 -0700


@@ -65,6 +65,8 @@ struct cpuinfo_x86 {
__u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy;

+ __u8 booted_cores;
+ __u8 apicid;


} ____cacheline_aligned;

#define X86_VENDOR_INTEL 0
@@ -91,6 +93,14 @@ extern char ignore_irq13;
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+extern int intel_num_cpu_cores(struct cpuinfo_x86 *c);
+
+#ifdef CONFIG_X86_HT
+extern void detect_ht(struct cpuinfo_x86 *c);
+#else
+static inline void detect_ht(struct cpuinfo_x86 *c) {}
+#endif
+

/*
* EFLAGS bits

diff -pNru linux-2.6.14-rc3/include/asm-x86_64/smp.h linux/include/asm-x86_64/smp.h


--- linux-2.6.14-rc3/include/asm-x86_64/smp.h 2005-09-30 14:17:35.000000000 -0700

+++ linux/include/asm-x86_64/smp.h 2005-10-07 16:27:37.714579368 -0700


@@ -57,6 +57,9 @@ extern cpumask_t cpu_core_map[NR_CPUS];
extern u8 phys_proc_id[NR_CPUS];
extern u8 cpu_core_id[NR_CPUS];

+extern void set_cpu_sibling_map(int);
+extern void remove_siblinginfo(int);
+
#define SMP_TRAMPOLINE_BASE 0x6000

/*

diff -pNru linux-2.6.14-rc3/include/linux/bitops.h linux/include/linux/bitops.h


--- linux-2.6.14-rc3/include/linux/bitops.h 2005-09-30 14:17:35.000000000 -0700

+++ linux/include/linux/bitops.h 2005-10-07 16:27:37.714579368 -0700


@@ -84,6 +84,16 @@ static __inline__ int get_bitmask_order(
return order; /* We could be slightly more clever with -1 here... */
}

+static __inline__ int get_count_order(unsigned int count)
+{
+ int order;
+
+ order = fls(count) - 1;
+ if (count & (count - 1))
+ order++;
+ return order;
+}
+
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word

Andi Kleen

unread,
Oct 8, 2005, 6:30:10 AM10/8/05
to
On Saturday 08 October 2005 02:52, Siddha, Suresh B wrote:
> On Fri, Oct 07, 2005 at 11:52:00AM +0200, Andi Kleen wrote:
> > > I can fix the API mess. Is there anything else you want me to do?
> >
> > I think you overdid the sharing. Can you limit it to one file
> > and copy the stuff that doesn't fit easily?
>
> Andi, This stuff is very much common to x86 and x86_64. Shared code is
> split into two files because setting up sibling map code is generic and
> HT/core detection code is very specific to Intel.
>
> How about the appended patch?

I would prefer if the Intel CPU detection support wasn't distributed over so
many small files. If you prefer to share it put it all into a single file and
share that. But please only for code that can be cleanly shared without
ifdefs.

Also in general it would be better if you first did the cleanup and then
as separate patches the various functionality enhancements.That makes
the changes easier to be reviewed and it helps in binary search when something
goes wrong.

-Andi

Siddha, Suresh B

unread,
Oct 12, 2005, 5:40:07 PM10/12/05
to
On Sat, Oct 08, 2005 at 12:28:38PM +0200, Andi Kleen wrote:
> On Saturday 08 October 2005 02:52, Siddha, Suresh B wrote:
> > On Fri, Oct 07, 2005 at 11:52:00AM +0200, Andi Kleen wrote:
> > > > I can fix the API mess. Is there anything else you want me to do?
> > >
> > > I think you overdid the sharing. Can you limit it to one file
> > > and copy the stuff that doesn't fit easily?
> >
> > Andi, This stuff is very much common to x86 and x86_64. Shared code is
> > split into two files because setting up sibling map code is generic and
> > HT/core detection code is very specific to Intel.
> >
> > How about the appended patch?
>
> I would prefer if the Intel CPU detection support wasn't distributed over so
> many small files. If you prefer to share it put it all into a single file and
> share that. But please only for code that can be cleanly shared without
> ifdefs.

Lets defer this code sharing to some other time. I want to make sure that
-mm tree (and finally 2.6.15) picks up these enhancements first, before
I start my vacation :)

> Also in general it would be better if you first did the cleanup and then
> as separate patches the various functionality enhancements.That makes
> the changes easier to be reviewed and it helps in binary search when something
> goes wrong.

I am going to send two follow up patches which addresses the functionality
enhancements.

thanks,
suresh

Siddha, Suresh B

unread,
Oct 12, 2005, 5:40:18 PM10/12/05
to
Andrew, Please apply.

thanks,
suresh
--

Fields obtained through cpuid vector 0x1(ebx[16:23]) and
vector 0x4(eax[14:25], eax[26:31]) indicate the maximum values and might not
always be the same as what is available and what OS sees. So make sure
"siblings" and "cpu cores" values in /proc/cpuinfo reflect the values as seen
by OS instead of what cpuid instruction says. This will also fix the buggy BIOS

cases (for example where cpuid on a single core cpu says there are "2" siblings,


even when HT is disabled in the BIOS.
http://bugzilla.kernel.org/show_bug.cgi?id=4359)

Signed-off-by: Suresh Siddha <suresh....@intel.com>

diff -pNru linux-2.6.14-rc4/arch/i386/kernel/cpu/common.c linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/common.c
--- linux-2.6.14-rc4/arch/i386/kernel/cpu/common.c 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/common.c 2005-10-12 11:02:00.361726016 -0700
@@ -446,32 +446,29 @@ void __devinit identify_cpu(struct cpuin
void __devinit detect_ht(struct cpuinfo_x86 *c)
{


u32 eax, ebx, ecx, edx;
- int index_msb, tmp;

+ int index_msb, core_bits;


int cpu = smp_processor_id();

+ cpuid(1, &eax, &ebx, &ecx, &edx);
+
+ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
+

if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))

return;



- cpuid(1, &eax, &ebx, &ecx, &edx);

smp_num_siblings = (ebx & 0xff0000) >> 16;

if (smp_num_siblings == 1) {


printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");

} else if (smp_num_siblings > 1 ) {
- index_msb = 31;

if (smp_num_siblings > NR_CPUS) {


printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);

smp_num_siblings = 1;
return;


}
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- index_msb--;
- }
- if (smp_num_siblings & (smp_num_siblings - 1))
- index_msb++;

+
+ index_msb = get_count_order(smp_num_siblings);

phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);

printk(KERN_INFO "CPU: Physical Processor ID: %d\n",

@@ -479,17 +476,12 @@ void __devinit detect_ht(struct cpuinfo_



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--;
- }

+ index_msb = get_count_order(smp_num_siblings) ;



- if (smp_num_siblings & (smp_num_siblings - 1))
- index_msb++;

+ core_bits = get_count_order(c->x86_num_cores);

- cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);

+ cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
+ ((1 << core_bits) - 1);

if (c->x86_num_cores > 1)


printk(KERN_INFO "CPU: Processor Core ID: %d\n",

diff -pNru linux-2.6.14-rc4/arch/i386/kernel/cpu/proc.c linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/proc.c
--- linux-2.6.14-rc4/arch/i386/kernel/cpu/proc.c 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/proc.c 2005-10-12 11:03:05.211867296 -0700
@@ -96,10 +96,9 @@ static int show_cpuinfo(struct seq_file
#ifdef CONFIG_X86_HT


if (c->x86_num_cores * smp_num_siblings > 1) {
seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);

- seq_printf(m, "siblings\t: %d\n",


- c->x86_num_cores * smp_num_siblings);

+ seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));


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);
+ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
#endif

diff -pNru linux-2.6.14-rc4/arch/i386/kernel/smpboot.c linux-2.6.14-rc4-dc/arch/i386/kernel/smpboot.c
--- linux-2.6.14-rc4/arch/i386/kernel/smpboot.c 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/arch/i386/kernel/smpboot.c 2005-10-12 11:12:53.383451624 -0700
@@ -440,35 +440,59 @@ static void __devinit smp_callin(void)

static int cpucount;

+static cpumask_t cpu_sibling_setup_map;
+
static inline void
set_cpu_sibling_map(int cpu)
{


int i;
+ struct cpuinfo_x86 *c = cpu_data;
+
+ cpu_set(cpu, cpu_sibling_setup_map);

if (smp_num_siblings > 1) {
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_isset(i, cpu_callout_map))
- continue;
- if (cpu_core_id[cpu] == cpu_core_id[i]) {

+ for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (phys_proc_id[cpu] == phys_proc_id[i] &&
+ cpu_core_id[cpu] == cpu_core_id[i]) {

cpu_set(i, cpu_sibling_map[cpu]);


cpu_set(cpu, cpu_sibling_map[i]);
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
}
}

} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}


- if (current_cpu_data.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]);
- cpu_set(cpu, cpu_core_map[i]);
- }
- }
- } else {

+ if (current_cpu_data.x86_num_cores == 1) {

@@ -1092,11 +1116,8 @@ static void __init smp_boot_cpus(unsigne



current_thread_info()->cpu = 0;
smp_tune_scheduling();
- 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]);

+ set_cpu_sibling_map(0);



/*
* If we couldn't find an SMP configuration at boot time,

@@ -1275,15 +1296,24 @@ static void
remove_siblinginfo(int cpu)
{


int sibling;
+ struct cpuinfo_x86 *c = cpu_data;

+ for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
+ cpu_clear(cpu, cpu_core_map[sibling]);
+ /*
+ * last thread sibling in this cpu core going down
+ */
+ if (cpus_weight(cpu_sibling_map[cpu]) == 1)
+ c[sibling].booted_cores--;
+ }
+

for_each_cpu_mask(sibling, cpu_sibling_map[cpu])


cpu_clear(cpu, cpu_sibling_map[sibling]);
- for_each_cpu_mask(sibling, cpu_core_map[cpu])
- cpu_clear(cpu, cpu_core_map[sibling]);

cpus_clear(cpu_sibling_map[cpu]);
cpus_clear(cpu_core_map[cpu]);
phys_proc_id[cpu] = BAD_APICID;


cpu_core_id[cpu] = BAD_APICID;
+ cpu_clear(cpu, cpu_sibling_setup_map);
}

int __cpu_disable(void)
diff -pNru linux-2.6.14-rc4/arch/x86_64/kernel/setup.c linux-2.6.14-rc4-dc/arch/x86_64/kernel/setup.c
--- linux-2.6.14-rc4/arch/x86_64/kernel/setup.c 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/arch/x86_64/kernel/setup.c 2005-10-12 11:29:43.188937856 -0700
@@ -889,52 +889,42 @@ static void __cpuinit detect_ht(struct c
{
#ifdef CONFIG_SMP


u32 eax, ebx, ecx, edx;
- int index_msb, tmp;

+ int index_msb, core_bits;


int cpu = smp_processor_id();
-

+
+ cpuid(1, &eax, &ebx, &ecx, &edx);
+

+ c->apicid = phys_pkg_id(0);


+
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))

return;



- cpuid(1, &eax, &ebx, &ecx, &edx);

smp_num_siblings = (ebx & 0xff0000) >> 16;
-

+
if (smp_num_siblings == 1) {

printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
- } else if (smp_num_siblings > 1) {
- index_msb = 31;
- /*
- * At this point we only support two siblings per
- * processor package.
- */

+ } else if (smp_num_siblings > 1 ) {
+

if (smp_num_siblings > NR_CPUS) {


printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);

smp_num_siblings = 1;
return;


}
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- index_msb--;
- }
- if (smp_num_siblings & (smp_num_siblings - 1))
- index_msb++;

+
+ index_msb = get_count_order(smp_num_siblings);

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++;

+ index_msb = get_count_order(smp_num_siblings) ;
+
+ core_bits = get_count_order(c->x86_num_cores);

- cpu_core_id[cpu] = phys_pkg_id(index_msb);

+ cpu_core_id[cpu] = phys_pkg_id(index_msb) &


+ ((1 << core_bits) - 1);

if (c->x86_num_cores > 1)


printk(KERN_INFO "CPU: Processor Core ID: %d\n",

@@ -1274,10 +1264,9 @@ static int show_cpuinfo(struct seq_file
if (smp_num_siblings * c->x86_num_cores > 1) {


int cpu = c - cpu_data;
seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);

- seq_printf(m, "siblings\t: %d\n",


- c->x86_num_cores * smp_num_siblings);

+ seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));


seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]);
- seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
+ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
#endif

diff -pNru linux-2.6.14-rc4/arch/x86_64/kernel/smpboot.c linux-2.6.14-rc4-dc/arch/x86_64/kernel/smpboot.c
--- linux-2.6.14-rc4/arch/x86_64/kernel/smpboot.c 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/arch/x86_64/kernel/smpboot.c 2005-10-12 11:17:34.109774736 -0700
@@ -436,30 +436,58 @@ void __cpuinit smp_callin(void)
cpu_set(cpuid, cpu_callin_map);
}

+static cpumask_t cpu_sibling_setup_map;
+
static inline void set_cpu_sibling_map(int cpu)
{


int i;
+ struct cpuinfo_x86 *c = cpu_data;
+
+ cpu_set(cpu, cpu_sibling_setup_map);

if (smp_num_siblings > 1) {
- for_each_cpu(i) {
- if (cpu_core_id[cpu] == cpu_core_id[i]) {

+ for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (phys_proc_id[cpu] == phys_proc_id[i] &&
+ cpu_core_id[cpu] == cpu_core_id[i]) {

cpu_set(i, cpu_sibling_map[cpu]);


cpu_set(cpu, cpu_sibling_map[i]);
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
}
}

} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}


- if (current_cpu_data.x86_num_cores > 1) {
- for_each_cpu(i) {
- if (phys_proc_id[cpu] == phys_proc_id[i]) {
- cpu_set(i, cpu_core_map[cpu]);
- cpu_set(cpu, cpu_core_map[i]);
- }
- }
- } else {

+ if (current_cpu_data.x86_num_cores == 1) {

@@ -966,6 +994,7 @@ void __init smp_prepare_cpus(unsigned in


nmi_watchdog_default();
current_cpu_data = boot_cpu_data;
current_thread_info()->cpu = 0; /* needed? */
+ set_cpu_sibling_map(0);

if (smp_sanity_check(max_cpus) < 0) {
printk(KERN_INFO "SMP disabled\n");
@@ -1009,8 +1038,6 @@ void __init smp_prepare_boot_cpu(void)


int me = smp_processor_id();
cpu_set(me, cpu_online_map);
cpu_set(me, cpu_callout_map);
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);

per_cpu(cpu_state, me) = CPU_ONLINE;
}

@@ -1082,15 +1109,24 @@ void __init smp_cpus_done(unsigned int m
static void remove_siblinginfo(int cpu)
{


int sibling;
+ struct cpuinfo_x86 *c = cpu_data;

+ for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
+ cpu_clear(cpu, cpu_core_map[sibling]);
+ /*
+ * last thread sibling in this cpu core going down
+ */
+ if (cpus_weight(cpu_sibling_map[cpu]) == 1)
+ c[sibling].booted_cores--;
+ }
+

for_each_cpu_mask(sibling, cpu_sibling_map[cpu])


cpu_clear(cpu, cpu_sibling_map[sibling]);
- for_each_cpu_mask(sibling, cpu_core_map[cpu])
- cpu_clear(cpu, cpu_core_map[sibling]);

cpus_clear(cpu_sibling_map[cpu]);
cpus_clear(cpu_core_map[cpu]);
phys_proc_id[cpu] = BAD_APICID;


cpu_core_id[cpu] = BAD_APICID;
+ cpu_clear(cpu, cpu_sibling_setup_map);
}

void remove_cpu_from_maps(void)
diff -pNru linux-2.6.14-rc4/include/asm-i386/processor.h linux-2.6.14-rc4-dc/include/asm-i386/processor.h
--- linux-2.6.14-rc4/include/asm-i386/processor.h 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/include/asm-i386/processor.h 2005-10-12 10:59:34.927835328 -0700


@@ -66,6 +66,8 @@ struct cpuinfo_x86 {
int coma_bug;
unsigned long loops_per_jiffy;
unsigned char x86_num_cores;
+ unsigned char booted_cores;
+ unsigned char apicid;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));

#define X86_VENDOR_INTEL 0

diff -pNru linux-2.6.14-rc4/include/asm-x86_64/processor.h linux-2.6.14-rc4-dc/include/asm-x86_64/processor.h
--- linux-2.6.14-rc4/include/asm-x86_64/processor.h 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/include/asm-x86_64/processor.h 2005-10-12 10:44:45.467053920 -0700


@@ -65,6 +65,8 @@ struct cpuinfo_x86 {
__u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy;

+ __u8 apicid;
+ __u8 booted_cores;
} ____cacheline_aligned;

#define X86_VENDOR_INTEL 0

diff -pNru linux-2.6.14-rc4/include/linux/bitops.h linux-2.6.14-rc4-dc/include/linux/bitops.h
--- linux-2.6.14-rc4/include/linux/bitops.h 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/include/linux/bitops.h 2005-10-12 11:17:52.585965928 -0700


@@ -84,6 +84,16 @@ static __inline__ int get_bitmask_order(
return order; /* We could be slightly more clever with -1 here... */
}

+static __inline__ int get_count_order(unsigned int count)
+{
+ int order;
+
+ order = fls(count) - 1;
+ if (count & (count - 1))
+ order++;
+ return order;
+}
+
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word

Siddha, Suresh B

unread,
Oct 12, 2005, 5:50:11 PM10/12/05
to
Andrew, Please apply.

thanks,
suresh
--

Fix the Intel cache detection code assumption that number of threads sharing the


cache will either be equal to number of HT or core siblings.

Signed-off-by: Suresh Siddha <suresh....@intel.com>

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_cacheinfo.c linux/arch/i386/kernel/cpu/intel_cacheinfo.c

Andi Kleen

unread,
Oct 12, 2005, 6:00:23 PM10/12/05
to
On Wednesday 12 October 2005 23:36, Siddha, Suresh B wrote:

> Fields obtained through cpuid vector 0x1(ebx[16:23]) and
> vector 0x4(eax[14:25], eax[26:31]) indicate the maximum values and might not
> always be the same as what is available and what OS sees. So make sure
> "siblings" and "cpu cores" values in /proc/cpuinfo reflect the values as seen
> by OS instead of what cpuid instruction says. This will also fix the buggy BIOS
> cases (for example where cpuid on a single core cpu says there are "2" siblings,
> even when HT is disabled in the BIOS.
> http://bugzilla.kernel.org/show_bug.cgi?id=4359)

I'm not too fond of this new booted_core variable. How about
you just put the true number of cores into x86_num_cores?
What should x86_num_cores be in your setup anyways if not
"booted cores"?

Also I must admit the number of different variables to keep
track of multicore and siblingness starts to become mindboggling,
so I would recommend you add a fat overview comment somewhere
that describes their definition and relationship. Or better put
something into Documentation, it is probably as confusing for
user space /proc/cpuinfo consumer too.

-Andi

Siddha, Suresh B

unread,
Oct 12, 2005, 6:30:15 PM10/12/05
to
On Wed, Oct 12, 2005 at 11:49:04PM +0200, Andi Kleen wrote:
> On Wednesday 12 October 2005 23:36, Siddha, Suresh B wrote:
>
> > Fields obtained through cpuid vector 0x1(ebx[16:23]) and
> > vector 0x4(eax[14:25], eax[26:31]) indicate the maximum values and might not
> > always be the same as what is available and what OS sees. So make sure
> > "siblings" and "cpu cores" values in /proc/cpuinfo reflect the values as seen
> > by OS instead of what cpuid instruction says. This will also fix the buggy BIOS
> > cases (for example where cpuid on a single core cpu says there are "2" siblings,
> > even when HT is disabled in the BIOS.
> > http://bugzilla.kernel.org/show_bug.cgi?id=4359)
>
> I'm not too fond of this new booted_core variable. How about
> you just put the true number of cores into x86_num_cores?
> What should x86_num_cores be in your setup anyways if not
> "booted cores"?

x86_num_cores (cpuid returned value) is required while right shifting the
apicid to get the core-id and the package-id. booted_cores will indicate
how many cores actually cameup. x86_num_cores can differ from "booted cores"
in these scenarios

a) x86_num_cores may not be '1' when multi-core is disabled in the BIOS
b) "maxcpus=" kernel boot param
c) logical hotplug

> Also I must admit the number of different variables to keep
> track of multicore and siblingness starts to become mindboggling,
> so I would recommend you add a fat overview comment somewhere
> that describes their definition and relationship. Or better put
> something into Documentation, it is probably as confusing for
> user space /proc/cpuinfo consumer too.

I will send a new documentation patch.

thanks,
suresh

Andi Kleen

unread,
Oct 12, 2005, 8:20:04 PM10/12/05
to
On Thursday 13 October 2005 00:19, Siddha, Suresh B wrote:

> x86_num_cores (cpuid returned value) is required while right shifting the
> apicid to get the core-id and the package-id. booted_cores will indicate
> how many cores actually cameup. x86_num_cores can differ from "booted cores"
> in these scenarios

The original idea was to round it up to the next power of two
before shifting. But I can see that it will break when the number
of online cores differs from the max number by more than a single power
of two (e.g. quadcore with only a single CPU booted)

Ok, if you rename the variable to make it clear

x86_num_cores -> x86_max_cores


-Andi

Siddha, Suresh B

unread,
Oct 13, 2005, 6:00:26 PM10/13/05
to
On Thu, Oct 13, 2005 at 02:10:22AM +0200, Andi Kleen wrote:
> Ok, if you rename the variable to make it clear
>
> x86_num_cores -> x86_max_cores

Andrew, please apply.

thanks,
suresh
--

Fields obtained through cpuid vector 0x1(ebx[16:23]) and
vector 0x4(eax[14:25], eax[26:31]) indicate the maximum values and might not
always be the same as what is available and what OS sees. So make sure
"siblings" and "cpu cores" values in /proc/cpuinfo reflect the values as seen
by OS instead of what cpuid instruction says. This will also fix the buggy BIOS
cases (for example where cpuid on a single core cpu says there are "2" siblings,
even when HT is disabled in the BIOS.
http://bugzilla.kernel.org/show_bug.cgi?id=4359)

Signed-off-by: Suresh Siddha <suresh....@intel.com>

diff -pNru linux-2.6.14-rc4/arch/i386/kernel/cpu/amd.c linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/amd.c
--- linux-2.6.14-rc4/arch/i386/kernel/cpu/amd.c 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/amd.c 2005-10-12 18:21:08.267235544 -0700
@@ -206,9 +206,9 @@ static void __init init_amd(struct cpuin
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;
+ c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+ if (c->x86_max_cores & (c->x86_max_cores - 1))
+ c->x86_max_cores = 1;
}

#ifdef CONFIG_X86_HT
@@ -217,15 +217,15 @@ static void __init init_amd(struct cpuin
* distingush the cores. Assumes number of cores is a power
* of two.
*/
- if (c->x86_num_cores > 1) {
+ if (c->x86_max_cores > 1) {
int cpu = smp_processor_id();
unsigned bits = 0;
- while ((1 << bits) < c->x86_num_cores)
+ while ((1 << bits) < c->x86_max_cores)
bits++;
cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
phys_proc_id[cpu] >>= bits;
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
- cpu, c->x86_num_cores, cpu_core_id[cpu]);
+ cpu, c->x86_max_cores, cpu_core_id[cpu]);
}
#endif


}
diff -pNru linux-2.6.14-rc4/arch/i386/kernel/cpu/common.c linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/common.c
--- linux-2.6.14-rc4/arch/i386/kernel/cpu/common.c 2005-10-10 18:19:19.000000000 -0700

+++ linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/common.c 2005-10-12 18:21:08.271234936 -0700
@@ -335,7 +335,7 @@ void __devinit identify_cpu(struct cpuin
c->x86_model = c->x86_mask = 0; /* So far unknown... */
c->x86_vendor_id[0] = '\0'; /* Unset */
c->x86_model_id[0] = '\0'; /* Unset */
- c->x86_num_cores = 1;
+ c->x86_max_cores = 1;
memset(&c->x86_capability, 0, sizeof c->x86_capability);

if (!have_cpuid_p()) {
@@ -446,52 +446,44 @@ void __devinit identify_cpu(struct cpuin


void __devinit detect_ht(struct cpuinfo_x86 *c)
{

u32 eax, ebx, ecx, edx;
- int index_msb, tmp;

+ int index_msb, core_bits;
int cpu = smp_processor_id();

+ cpuid(1, &eax, &ebx, &ecx, &edx);
+


+ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);

+
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))

return;



- cpuid(1, &eax, &ebx, &ecx, &edx);

smp_num_siblings = (ebx & 0xff0000) >> 16;

if (smp_num_siblings == 1) {


printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");

} else if (smp_num_siblings > 1 ) {
- index_msb = 31;

if (smp_num_siblings > NR_CPUS) {


printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);

smp_num_siblings = 1;
return;


}
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- index_msb--;
- }
- if (smp_num_siblings & (smp_num_siblings - 1))
- index_msb++;

+
+ index_msb = get_count_order(smp_num_siblings);

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;

+ smp_num_siblings = smp_num_siblings / c->x86_max_cores;



- tmp = smp_num_siblings;
- index_msb = 31;
- while ((tmp & 0x80000000) == 0) {
- tmp <<=1 ;
- index_msb--;
- }

+ index_msb = get_count_order(smp_num_siblings) ;



- if (smp_num_siblings & (smp_num_siblings - 1))
- index_msb++;

+ core_bits = get_count_order(c->x86_max_cores);



- cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);

+ cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
+ ((1 << core_bits) - 1);

- if (c->x86_num_cores > 1)

+ if (c->x86_max_cores > 1)


printk(KERN_INFO "CPU: Processor Core ID: %d\n",

cpu_core_id[cpu]);
}
diff -pNru linux-2.6.14-rc4/arch/i386/kernel/cpu/intel.c linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/intel.c
--- linux-2.6.14-rc4/arch/i386/kernel/cpu/intel.c 2005-10-10 18:19:19.000000000 -0700
+++ linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/intel.c 2005-10-12 18:21:08.273234632 -0700
@@ -157,7 +157,7 @@ static void __devinit init_intel(struct

if ( p )
strcpy(c->x86_model_id, p);

- c->x86_num_cores = num_cpu_cores(c);

+ c->x86_max_cores = num_cpu_cores(c);

detect_ht(c);

diff -pNru linux-2.6.14-rc4/arch/i386/kernel/cpu/intel_cacheinfo.c linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/intel_cacheinfo.c
--- linux-2.6.14-rc4/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-10-13 13:56:15.405521280 -0700
+++ linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-10-13 13:56:47.645620040 -0700
@@ -317,7 +317,7 @@ static void __devinit cache_shared_cpu_m
#ifdef CONFIG_X86_HT


else if (num_threads_sharing == smp_num_siblings)

this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
- else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings))

+ else if (num_threads_sharing == (c->x86_max_cores * smp_num_siblings))


this_leaf->shared_cpu_map = cpu_core_map[cpu];

else


printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "

diff -pNru linux-2.6.14-rc4/arch/i386/kernel/cpu/proc.c linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/proc.c
--- linux-2.6.14-rc4/arch/i386/kernel/cpu/proc.c 2005-10-10 18:19:19.000000000 -0700

+++ linux-2.6.14-rc4-dc/arch/i386/kernel/cpu/proc.c 2005-10-12 18:21:08.289232200 -0700
@@ -94,12 +94,11 @@ static int show_cpuinfo(struct seq_file
if (c->x86_cache_size >= 0)
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
#ifdef CONFIG_X86_HT
- if (c->x86_num_cores * smp_num_siblings > 1) {
+ if (c->x86_max_cores * smp_num_siblings > 1) {


seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);

- seq_printf(m, "siblings\t: %d\n",


- c->x86_num_cores * smp_num_siblings);

+ seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));


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);
+ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
#endif

diff -pNru linux-2.6.14-rc4/arch/i386/kernel/smpboot.c linux-2.6.14-rc4-dc/arch/i386/kernel/smpboot.c
--- linux-2.6.14-rc4/arch/i386/kernel/smpboot.c 2005-10-10 18:19:19.000000000 -0700

+++ linux-2.6.14-rc4-dc/arch/i386/kernel/smpboot.c 2005-10-13 13:58:26.266627368 -0700
@@ -74,9 +74,11 @@ EXPORT_SYMBOL(phys_proc_id);
int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
EXPORT_SYMBOL(cpu_core_id);

+/* representing HT siblings of each logical CPU */
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_sibling_map);

+/* representing HT and core siblings of each logical CPU */
cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_core_map);

@@ -440,35 +442,60 @@ static void __devinit smp_callin(void)

static int cpucount;

+/* representing cpus for which sibling maps can be computed */


+static cpumask_t cpu_sibling_setup_map;
+
static inline void
set_cpu_sibling_map(int cpu)
{

int i;
+ struct cpuinfo_x86 *c = cpu_data;
+
+ cpu_set(cpu, cpu_sibling_setup_map);

if (smp_num_siblings > 1) {
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_isset(i, cpu_callout_map))
- continue;
- if (cpu_core_id[cpu] == cpu_core_id[i]) {

+ for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (phys_proc_id[cpu] == phys_proc_id[i] &&
+ cpu_core_id[cpu] == cpu_core_id[i]) {

cpu_set(i, cpu_sibling_map[cpu]);


cpu_set(cpu, cpu_sibling_map[i]);
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
}
}

} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}


- if (current_cpu_data.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]);
- cpu_set(cpu, cpu_core_map[i]);
- }
- }
- } else {

+ if (current_cpu_data.x86_max_cores == 1) {

@@ -1092,11 +1119,8 @@ static void __init smp_boot_cpus(unsigne



current_thread_info()->cpu = 0;
smp_tune_scheduling();
- 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]);

+ set_cpu_sibling_map(0);



/*
* If we couldn't find an SMP configuration at boot time,

@@ -1275,15 +1299,24 @@ static void
remove_siblinginfo(int cpu)
{


int sibling;
+ struct cpuinfo_x86 *c = cpu_data;

+ for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
+ cpu_clear(cpu, cpu_core_map[sibling]);
+ /*
+ * last thread sibling in this cpu core going down
+ */
+ if (cpus_weight(cpu_sibling_map[cpu]) == 1)
+ c[sibling].booted_cores--;
+ }
+

for_each_cpu_mask(sibling, cpu_sibling_map[cpu])


cpu_clear(cpu, cpu_sibling_map[sibling]);
- for_each_cpu_mask(sibling, cpu_core_map[cpu])
- cpu_clear(cpu, cpu_core_map[sibling]);

cpus_clear(cpu_sibling_map[cpu]);
cpus_clear(cpu_core_map[cpu]);
phys_proc_id[cpu] = BAD_APICID;

cpu_core_id[cpu] = BAD_APICID;
+ cpu_clear(cpu, cpu_sibling_setup_map);
}

int __cpu_disable(void)
diff -pNru linux-2.6.14-rc4/arch/x86_64/kernel/setup.c linux-2.6.14-rc4-dc/arch/x86_64/kernel/setup.c

--- linux-2.6.14-rc4/arch/x86_64/kernel/setup.c 2005-10-12 18:22:04.262722936 -0700
+++ linux-2.6.14-rc4-dc/arch/x86_64/kernel/setup.c 2005-10-12 18:21:08.298230832 -0700
@@ -793,7 +793,7 @@ static void __init amd_detect_cmp(struct
#endif

bits = 0;
- while ((1 << bits) < c->x86_num_cores)
+ while ((1 << bits) < c->x86_max_cores)
bits++;

/* Low order bits define the core id (index of core in socket) */
@@ -826,7 +826,7 @@ static void __init amd_detect_cmp(struct
cpu_to_node[cpu] = node;

printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
- cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
+ cpu, c->x86_max_cores, node, cpu_core_id[cpu]);
#endif
#endif
}
@@ -875,9 +875,9 @@ static int __init init_amd(struct cpuinf
display_cacheinfo(c);

if (c->extended_cpuid_level >= 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;
+ c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+ if (c->x86_max_cores & (c->x86_max_cores - 1))
+ c->x86_max_cores = 1;

amd_detect_cmp(c);
}
@@ -889,54 +889,44 @@ static void __cpuinit detect_ht(struct c
{
#ifdef CONFIG_SMP


u32 eax, ebx, ecx, edx;
- int index_msb, tmp;

+ int index_msb, core_bits;


int cpu = smp_processor_id();
-

+
+ cpuid(1, &eax, &ebx, &ecx, &edx);
+

+ c->apicid = phys_pkg_id(0);

+
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))

return;



- cpuid(1, &eax, &ebx, &ecx, &edx);

smp_num_siblings = (ebx & 0xff0000) >> 16;
-

+
if (smp_num_siblings == 1) {

printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
- } else if (smp_num_siblings > 1) {
- index_msb = 31;
- /*
- * At this point we only support two siblings per
- * processor package.
- */

+ } else if (smp_num_siblings > 1 ) {
+

if (smp_num_siblings > NR_CPUS) {


printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);

smp_num_siblings = 1;
return;


}
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- index_msb--;
- }
- if (smp_num_siblings & (smp_num_siblings - 1))
- index_msb++;

+
+ index_msb = get_count_order(smp_num_siblings);

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;

+ smp_num_siblings = smp_num_siblings / c->x86_max_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++;

+ index_msb = get_count_order(smp_num_siblings) ;
+

+ core_bits = get_count_order(c->x86_max_cores);



- cpu_core_id[cpu] = phys_pkg_id(index_msb);

+ cpu_core_id[cpu] = phys_pkg_id(index_msb) &
+ ((1 << core_bits) - 1);

- if (c->x86_num_cores > 1)

+ if (c->x86_max_cores > 1)


printk(KERN_INFO "CPU: Processor Core ID: %d\n",

cpu_core_id[cpu]);
}
@@ -999,7 +989,7 @@ static void __cpuinit init_intel(struct
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);
+ c->x86_max_cores = intel_num_cpu_cores(c);

srat_detect_node();
}
@@ -1037,7 +1027,7 @@ void __cpuinit early_identify_cpu(struct
c->x86_model_id[0] = '\0'; /* Unset */
c->x86_clflush_size = 64;
c->x86_cache_alignment = c->x86_clflush_size;
- c->x86_num_cores = 1;
+ c->x86_max_cores = 1;
c->extended_cpuid_level = 0;
memset(&c->x86_capability, 0, sizeof c->x86_capability);

@@ -1271,13 +1261,12 @@ static int show_cpuinfo(struct seq_file
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);

#ifdef CONFIG_SMP
- if (smp_num_siblings * c->x86_num_cores > 1) {
+ if (smp_num_siblings * c->x86_max_cores > 1) {


int cpu = c - cpu_data;
seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);

- seq_printf(m, "siblings\t: %d\n",


- c->x86_num_cores * smp_num_siblings);

+ seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));


seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]);
- seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
+ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
}
#endif

diff -pNru linux-2.6.14-rc4/arch/x86_64/kernel/smpboot.c linux-2.6.14-rc4-dc/arch/x86_64/kernel/smpboot.c
--- linux-2.6.14-rc4/arch/x86_64/kernel/smpboot.c 2005-10-12 18:22:04.263722784 -0700
+++ linux-2.6.14-rc4-dc/arch/x86_64/kernel/smpboot.c 2005-10-13 13:58:36.485073928 -0700
@@ -64,6 +64,7 @@
int smp_num_siblings = 1;
/* Package ID of each logical CPU */
u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+/* core ID of each logical CPU */
u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
EXPORT_SYMBOL(phys_proc_id);
EXPORT_SYMBOL(cpu_core_id);
@@ -89,7 +90,10 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __c
/* Set when the idlers are all forked */
int smp_threads_ready;

+/* representing HT siblings of each logical CPU */
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
+
+/* representing HT and core siblings of each logical CPU */
cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_core_map);

@@ -436,30 +440,59 @@ void __cpuinit smp_callin(void)
cpu_set(cpuid, cpu_callin_map);
}

+/* representing cpus for which sibling maps can be computed */


+static cpumask_t cpu_sibling_setup_map;
+
static inline void set_cpu_sibling_map(int cpu)
{

int i;
+ struct cpuinfo_x86 *c = cpu_data;
+
+ cpu_set(cpu, cpu_sibling_setup_map);

if (smp_num_siblings > 1) {
- for_each_cpu(i) {
- if (cpu_core_id[cpu] == cpu_core_id[i]) {

+ for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (phys_proc_id[cpu] == phys_proc_id[i] &&
+ cpu_core_id[cpu] == cpu_core_id[i]) {

cpu_set(i, cpu_sibling_map[cpu]);


cpu_set(cpu, cpu_sibling_map[i]);
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
}
}

} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}


- if (current_cpu_data.x86_num_cores > 1) {
- for_each_cpu(i) {
- if (phys_proc_id[cpu] == phys_proc_id[i]) {
- cpu_set(i, cpu_core_map[cpu]);
- cpu_set(cpu, cpu_core_map[i]);
- }
- }
- } else {

+ if (current_cpu_data.x86_max_cores == 1) {

@@ -966,6 +999,7 @@ void __init smp_prepare_cpus(unsigned in


nmi_watchdog_default();
current_cpu_data = boot_cpu_data;
current_thread_info()->cpu = 0; /* needed? */
+ set_cpu_sibling_map(0);

if (smp_sanity_check(max_cpus) < 0) {
printk(KERN_INFO "SMP disabled\n");

@@ -1009,8 +1043,6 @@ void __init smp_prepare_boot_cpu(void)


int me = smp_processor_id();
cpu_set(me, cpu_online_map);
cpu_set(me, cpu_callout_map);
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);

per_cpu(cpu_state, me) = CPU_ONLINE;
}

@@ -1082,15 +1114,24 @@ void __init smp_cpus_done(unsigned int m
static void remove_siblinginfo(int cpu)
{


int sibling;
+ struct cpuinfo_x86 *c = cpu_data;

+ for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
+ cpu_clear(cpu, cpu_core_map[sibling]);
+ /*
+ * last thread sibling in this cpu core going down
+ */
+ if (cpus_weight(cpu_sibling_map[cpu]) == 1)
+ c[sibling].booted_cores--;
+ }
+

for_each_cpu_mask(sibling, cpu_sibling_map[cpu])


cpu_clear(cpu, cpu_sibling_map[sibling]);
- for_each_cpu_mask(sibling, cpu_core_map[cpu])
- cpu_clear(cpu, cpu_core_map[sibling]);

cpus_clear(cpu_sibling_map[cpu]);
cpus_clear(cpu_core_map[cpu]);
phys_proc_id[cpu] = BAD_APICID;

cpu_core_id[cpu] = BAD_APICID;
+ cpu_clear(cpu, cpu_sibling_setup_map);
}

void remove_cpu_from_maps(void)
diff -pNru linux-2.6.14-rc4/include/asm-i386/processor.h linux-2.6.14-rc4-dc/include/asm-i386/processor.h
--- linux-2.6.14-rc4/include/asm-i386/processor.h 2005-10-10 18:19:19.000000000 -0700

+++ linux-2.6.14-rc4-dc/include/asm-i386/processor.h 2005-10-13 13:40:54.128576664 -0700
@@ -65,7 +65,9 @@ struct cpuinfo_x86 {
int f00f_bug;


int coma_bug;
unsigned long loops_per_jiffy;

- unsigned char x86_num_cores;
+ unsigned char x86_max_cores; /* cpuid returned max cores value */
+ unsigned char booted_cores; /* number of cores as seen by OS */


+ unsigned char apicid;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));

#define X86_VENDOR_INTEL 0

diff -pNru linux-2.6.14-rc4/include/asm-x86_64/processor.h linux-2.6.14-rc4-dc/include/asm-x86_64/processor.h
--- linux-2.6.14-rc4/include/asm-x86_64/processor.h 2005-10-10 18:19:19.000000000 -0700

+++ linux-2.6.14-rc4-dc/include/asm-x86_64/processor.h 2005-10-13 13:41:53.880492992 -0700
@@ -61,10 +61,12 @@ struct cpuinfo_x86 {
int x86_cache_alignment;
int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/
__u8 x86_virt_bits, x86_phys_bits;
- __u8 x86_num_cores;
+ __u8 x86_max_cores; /* cpuid returned max cores value */


__u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy;
+ __u8 apicid;

+ __u8 booted_cores; /* number of cores as seen by OS */


} ____cacheline_aligned;

#define X86_VENDOR_INTEL 0
diff -pNru linux-2.6.14-rc4/include/linux/bitops.h linux-2.6.14-rc4-dc/include/linux/bitops.h
--- linux-2.6.14-rc4/include/linux/bitops.h 2005-10-10 18:19:19.000000000 -0700

+++ linux-2.6.14-rc4-dc/include/linux/bitops.h 2005-10-12 11:17:52.585965928 -0700


@@ -84,6 +84,16 @@ static __inline__ int get_bitmask_order(
return order; /* We could be slightly more clever with -1 here... */
}

+static __inline__ int get_count_order(unsigned int count)
+{
+ int order;
+
+ order = fls(count) - 1;
+ if (count & (count - 1))
+ order++;
+ return order;
+}
+
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word

Siddha, Suresh B

unread,
Oct 13, 2005, 6:00:35 PM10/13/05
to
On Thu, Oct 13, 2005 at 02:10:22AM +0200, Andi Kleen wrote:
> Ok, if you rename the variable to make it clear
>
> x86_num_cores -> x86_max_cores

Updated patch 2/2 in the context of this change.

Andrew, please apply.

thanks,
suresh
--

Fix the Intel cache detection code assumption that number of threads sharing the


cache will either be equal to number of HT or core siblings.

Signed-off-by: Suresh Siddha <suresh....@intel.com>

diff -pNru linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_cacheinfo.c linux/arch/i386/kernel/cpu/intel_cacheinfo.c


--- linux-2.6.14-rc3/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-09-30 14:17:35.000000000 -0700

+++ linux/arch/i386/kernel/cpu/intel_cacheinfo.c 2005-10-07 16:27:37.708580280 -0700


@@ -303,29 +303,45 @@ static struct _cpuid4_info *cpuid4_info[
#ifdef CONFIG_SMP
static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
{
- struct _cpuid4_info *this_leaf;
+ struct _cpuid4_info *this_leaf, *sibling_leaf;
unsigned long num_threads_sharing;
-#ifdef CONFIG_X86_HT
- struct cpuinfo_x86 *c = cpu_data + cpu;
-#endif
+ int index_msb, i;
+ struct cpuinfo_x86 *c = cpu_data;

this_leaf = CPUID4_INFO_IDX(cpu, index);
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;

if (num_threads_sharing == 1)
cpu_set(cpu, this_leaf->shared_cpu_map);
-#ifdef CONFIG_X86_HT
- else if (num_threads_sharing == smp_num_siblings)
- this_leaf->shared_cpu_map = cpu_sibling_map[cpu];

- else if (num_threads_sharing == (c->x86_max_cores * smp_num_siblings))

0 new messages