Commit 94605eff authored by Siddha, Suresh B's avatar Siddha, Suresh B Committed by Linus Torvalds

[PATCH] x86-64/i386: Intel HT, Multi core detection fixes

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: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e90f22ed
...@@ -206,9 +206,9 @@ static void __init init_amd(struct cpuinfo_x86 *c) ...@@ -206,9 +206,9 @@ static void __init init_amd(struct cpuinfo_x86 *c)
display_cacheinfo(c); display_cacheinfo(c);
if (cpuid_eax(0x80000000) >= 0x80000008) { if (cpuid_eax(0x80000000) >= 0x80000008) {
c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
if (c->x86_num_cores & (c->x86_num_cores - 1)) if (c->x86_max_cores & (c->x86_max_cores - 1))
c->x86_num_cores = 1; c->x86_max_cores = 1;
} }
#ifdef CONFIG_X86_HT #ifdef CONFIG_X86_HT
...@@ -217,15 +217,15 @@ static void __init init_amd(struct cpuinfo_x86 *c) ...@@ -217,15 +217,15 @@ static void __init init_amd(struct cpuinfo_x86 *c)
* distingush the cores. Assumes number of cores is a power * distingush the cores. Assumes number of cores is a power
* of two. * of two.
*/ */
if (c->x86_num_cores > 1) { if (c->x86_max_cores > 1) {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
unsigned bits = 0; unsigned bits = 0;
while ((1 << bits) < c->x86_num_cores) while ((1 << bits) < c->x86_max_cores)
bits++; bits++;
cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
phys_proc_id[cpu] >>= bits; phys_proc_id[cpu] >>= bits;
printk(KERN_INFO "CPU %d(%d) -> Core %d\n", 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 #endif
} }
......
...@@ -335,7 +335,7 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) ...@@ -335,7 +335,7 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
c->x86_model = c->x86_mask = 0; /* So far unknown... */ c->x86_model = c->x86_mask = 0; /* So far unknown... */
c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_vendor_id[0] = '\0'; /* Unset */
c->x86_model_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); memset(&c->x86_capability, 0, sizeof c->x86_capability);
if (!have_cpuid_p()) { if (!have_cpuid_p()) {
...@@ -446,52 +446,44 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) ...@@ -446,52 +446,44 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
void __devinit detect_ht(struct cpuinfo_x86 *c) void __devinit detect_ht(struct cpuinfo_x86 *c)
{ {
u32 eax, ebx, ecx, edx; u32 eax, ebx, ecx, edx;
int index_msb, tmp; int index_msb, core_bits;
int cpu = smp_processor_id(); 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)) if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
return; return;
cpuid(1, &eax, &ebx, &ecx, &edx);
smp_num_siblings = (ebx & 0xff0000) >> 16; smp_num_siblings = (ebx & 0xff0000) >> 16;
if (smp_num_siblings == 1) { if (smp_num_siblings == 1) {
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
} else if (smp_num_siblings > 1 ) { } else if (smp_num_siblings > 1 ) {
index_msb = 31;
if (smp_num_siblings > NR_CPUS) { if (smp_num_siblings > NR_CPUS) {
printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
smp_num_siblings = 1; smp_num_siblings = 1;
return; return;
} }
tmp = smp_num_siblings;
while ((tmp & 0x80000000 ) == 0) { index_msb = get_count_order(smp_num_siblings);
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); phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
printk(KERN_INFO "CPU: Physical Processor ID: %d\n", printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
phys_proc_id[cpu]); 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 = get_count_order(smp_num_siblings) ;
index_msb = 31;
while ((tmp & 0x80000000) == 0) {
tmp <<=1 ;
index_msb--;
}
if (smp_num_siblings & (smp_num_siblings - 1)) core_bits = get_count_order(c->x86_max_cores);
index_msb++;
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", printk(KERN_INFO "CPU: Processor Core ID: %d\n",
cpu_core_id[cpu]); cpu_core_id[cpu]);
} }
......
...@@ -157,7 +157,7 @@ static void __devinit init_intel(struct cpuinfo_x86 *c) ...@@ -157,7 +157,7 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
if ( p ) if ( p )
strcpy(c->x86_model_id, 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); detect_ht(c);
......
...@@ -307,7 +307,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) ...@@ -307,7 +307,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
#ifdef CONFIG_X86_HT #ifdef CONFIG_X86_HT
else if (num_threads_sharing == smp_num_siblings) else if (num_threads_sharing == smp_num_siblings)
this_leaf->shared_cpu_map = cpu_sibling_map[cpu]; 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]; this_leaf->shared_cpu_map = cpu_core_map[cpu];
else else
printk(KERN_DEBUG "Number of CPUs sharing cache didn't match " printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "
......
...@@ -94,12 +94,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -94,12 +94,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (c->x86_cache_size >= 0) if (c->x86_cache_size >= 0)
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
#ifdef CONFIG_X86_HT #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, "physical id\t: %d\n", phys_proc_id[n]);
seq_printf(m, "siblings\t: %d\n", seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));
c->x86_num_cores * smp_num_siblings);
seq_printf(m, "core id\t\t: %d\n", cpu_core_id[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 #endif
......
...@@ -74,9 +74,11 @@ EXPORT_SYMBOL(phys_proc_id); ...@@ -74,9 +74,11 @@ EXPORT_SYMBOL(phys_proc_id);
int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
EXPORT_SYMBOL(cpu_core_id); EXPORT_SYMBOL(cpu_core_id);
/* representing HT siblings of each logical CPU */
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_sibling_map); EXPORT_SYMBOL(cpu_sibling_map);
/* representing HT and core siblings of each logical CPU */
cpumask_t cpu_core_map[NR_CPUS] __read_mostly; cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_core_map); EXPORT_SYMBOL(cpu_core_map);
...@@ -444,35 +446,60 @@ static void __devinit smp_callin(void) ...@@ -444,35 +446,60 @@ static void __devinit smp_callin(void)
static int cpucount; static int cpucount;
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
static inline void static inline void
set_cpu_sibling_map(int cpu) set_cpu_sibling_map(int cpu)
{ {
int i; int i;
struct cpuinfo_x86 *c = cpu_data;
cpu_set(cpu, cpu_sibling_setup_map);
if (smp_num_siblings > 1) { if (smp_num_siblings > 1) {
for (i = 0; i < NR_CPUS; i++) { for_each_cpu_mask(i, cpu_sibling_setup_map) {
if (!cpu_isset(i, cpu_callout_map)) if (phys_proc_id[cpu] == phys_proc_id[i] &&
continue; cpu_core_id[cpu] == cpu_core_id[i]) {
if (cpu_core_id[cpu] == cpu_core_id[i]) {
cpu_set(i, cpu_sibling_map[cpu]); cpu_set(i, cpu_sibling_map[cpu]);
cpu_set(cpu, cpu_sibling_map[i]); cpu_set(cpu, cpu_sibling_map[i]);
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
} }
} }
} else { } else {
cpu_set(cpu, cpu_sibling_map[cpu]); cpu_set(cpu, cpu_sibling_map[cpu]);
} }
if (current_cpu_data.x86_num_cores > 1) { if (current_cpu_data.x86_max_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]; 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;
}
} }
} }
...@@ -1096,11 +1123,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) ...@@ -1096,11 +1123,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
current_thread_info()->cpu = 0; current_thread_info()->cpu = 0;
smp_tune_scheduling(); smp_tune_scheduling();
cpus_clear(cpu_sibling_map[0]);
cpu_set(0, cpu_sibling_map[0]);
cpus_clear(cpu_core_map[0]); set_cpu_sibling_map(0);
cpu_set(0, cpu_core_map[0]);
/* /*
* If we couldn't find an SMP configuration at boot time, * If we couldn't find an SMP configuration at boot time,
...@@ -1279,15 +1303,24 @@ static void ...@@ -1279,15 +1303,24 @@ static void
remove_siblinginfo(int cpu) remove_siblinginfo(int cpu)
{ {
int sibling; 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]) for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
cpu_clear(cpu, cpu_sibling_map[sibling]); 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_sibling_map[cpu]);
cpus_clear(cpu_core_map[cpu]); cpus_clear(cpu_core_map[cpu]);
phys_proc_id[cpu] = BAD_APICID; phys_proc_id[cpu] = BAD_APICID;
cpu_core_id[cpu] = BAD_APICID; cpu_core_id[cpu] = BAD_APICID;
cpu_clear(cpu, cpu_sibling_setup_map);
} }
int __cpu_disable(void) int __cpu_disable(void)
......
...@@ -795,7 +795,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) ...@@ -795,7 +795,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
#endif #endif
bits = 0; bits = 0;
while ((1 << bits) < c->x86_num_cores) while ((1 << bits) < c->x86_max_cores)
bits++; bits++;
/* Low order bits define the core id (index of core in socket) */ /* Low order bits define the core id (index of core in socket) */
...@@ -828,7 +828,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) ...@@ -828,7 +828,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
numa_set_node(cpu, node); numa_set_node(cpu, node);
printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", 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
#endif #endif
} }
...@@ -877,9 +877,9 @@ static int __init init_amd(struct cpuinfo_x86 *c) ...@@ -877,9 +877,9 @@ static int __init init_amd(struct cpuinfo_x86 *c)
display_cacheinfo(c); display_cacheinfo(c);
if (c->extended_cpuid_level >= 0x80000008) { if (c->extended_cpuid_level >= 0x80000008) {
c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
if (c->x86_num_cores & (c->x86_num_cores - 1)) if (c->x86_max_cores & (c->x86_max_cores - 1))
c->x86_num_cores = 1; c->x86_max_cores = 1;
amd_detect_cmp(c); amd_detect_cmp(c);
} }
...@@ -891,54 +891,44 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c) ...@@ -891,54 +891,44 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
u32 eax, ebx, ecx, edx; u32 eax, ebx, ecx, edx;
int index_msb, tmp; int index_msb, core_bits;
int cpu = smp_processor_id(); 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)) if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
return; return;
cpuid(1, &eax, &ebx, &ecx, &edx);
smp_num_siblings = (ebx & 0xff0000) >> 16; smp_num_siblings = (ebx & 0xff0000) >> 16;
if (smp_num_siblings == 1) { if (smp_num_siblings == 1) {
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
} else if (smp_num_siblings > 1) { } 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) { if (smp_num_siblings > NR_CPUS) {
printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
smp_num_siblings = 1; smp_num_siblings = 1;
return; return;
} }
tmp = smp_num_siblings;
while ((tmp & 0x80000000 ) == 0) { index_msb = get_count_order(smp_num_siblings);
tmp <<=1 ;
index_msb--;
}
if (smp_num_siblings & (smp_num_siblings - 1))
index_msb++;
phys_proc_id[cpu] = phys_pkg_id(index_msb); phys_proc_id[cpu] = phys_pkg_id(index_msb);
printk(KERN_INFO "CPU: Physical Processor ID: %d\n", printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
phys_proc_id[cpu]); 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 = get_count_order(smp_num_siblings) ;
index_msb = 31;
while ((tmp & 0x80000000) == 0) { core_bits = get_count_order(c->x86_max_cores);
tmp <<=1 ;
index_msb--;
}
if (smp_num_siblings & (smp_num_siblings - 1))
index_msb++;
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", printk(KERN_INFO "CPU: Processor Core ID: %d\n",
cpu_core_id[cpu]); cpu_core_id[cpu]);
} }
...@@ -1006,7 +996,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) ...@@ -1006,7 +996,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
c->x86_cache_alignment = c->x86_clflush_size * 2; c->x86_cache_alignment = c->x86_clflush_size * 2;
if (c->x86 >= 15) if (c->x86 >= 15)
set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); 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(); srat_detect_node();
} }
...@@ -1044,7 +1034,7 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) ...@@ -1044,7 +1034,7 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
c->x86_model_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */
c->x86_clflush_size = 64; c->x86_clflush_size = 64;
c->x86_cache_alignment = c->x86_clflush_size; c->x86_cache_alignment = c->x86_clflush_size;
c->x86_num_cores = 1; c->x86_max_cores = 1;
c->extended_cpuid_level = 0; c->extended_cpuid_level = 0;
memset(&c->x86_capability, 0, sizeof c->x86_capability); memset(&c->x86_capability, 0, sizeof c->x86_capability);
...@@ -1278,13 +1268,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -1278,13 +1268,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
#ifdef CONFIG_SMP #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; int cpu = c - cpu_data;
seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]); seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);
seq_printf(m, "siblings\t: %d\n", seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
c->x86_num_cores * smp_num_siblings);
seq_printf(m, "core id\t\t: %d\n", cpu_core_id[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 #endif
......
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
int smp_num_siblings = 1; int smp_num_siblings = 1;
/* Package ID of each logical CPU */ /* Package ID of each logical CPU */
u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; 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 }; u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
EXPORT_SYMBOL(phys_proc_id); EXPORT_SYMBOL(phys_proc_id);
EXPORT_SYMBOL(cpu_core_id); EXPORT_SYMBOL(cpu_core_id);
...@@ -89,7 +90,10 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; ...@@ -89,7 +90,10 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
/* Set when the idlers are all forked */ /* Set when the idlers are all forked */
int smp_threads_ready; int smp_threads_ready;
/* representing HT siblings of each logical CPU */
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; 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; cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_core_map); EXPORT_SYMBOL(cpu_core_map);
...@@ -436,30 +440,59 @@ void __cpuinit smp_callin(void) ...@@ -436,30 +440,59 @@ void __cpuinit smp_callin(void)
cpu_set(cpuid, cpu_callin_map); 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) static inline void set_cpu_sibling_map(int cpu)
{ {
int i; int i;
struct cpuinfo_x86 *c = cpu_data;
cpu_set(cpu, cpu_sibling_setup_map);
if (smp_num_siblings > 1) { if (smp_num_siblings > 1) {
for_each_cpu(i) { for_each_cpu_mask(i, cpu_sibling_setup_map) {
if (cpu_core_id[cpu] == cpu_core_id[i]) { 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(i, cpu_sibling_map[cpu]);
cpu_set(cpu, cpu_sibling_map[i]); cpu_set(cpu, cpu_sibling_map[i]);
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
} }
} }
} else { } else {
cpu_set(cpu, cpu_sibling_map[cpu]); cpu_set(cpu, cpu_sibling_map[cpu]);
} }
if (current_cpu_data.x86_num_cores > 1) { if (current_cpu_data.x86_max_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]; 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;
}
} }
} }
...@@ -993,6 +1026,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -993,6 +1026,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
nmi_watchdog_default(); nmi_watchdog_default();
current_cpu_data = boot_cpu_data; current_cpu_data = boot_cpu_data;
current_thread_info()->cpu = 0; /* needed? */ current_thread_info()->cpu = 0; /* needed? */
set_cpu_sibling_map(0);
if (smp_sanity_check(max_cpus) < 0) { if (smp_sanity_check(max_cpus) < 0) {
printk(KERN_INFO "SMP disabled\n"); printk(KERN_INFO "SMP disabled\n");
...@@ -1036,8 +1070,6 @@ void __init smp_prepare_boot_cpu(void) ...@@ -1036,8 +1070,6 @@ void __init smp_prepare_boot_cpu(void)
int me = smp_processor_id(); int me = smp_processor_id();
cpu_set(me, cpu_online_map); cpu_set(me, cpu_online_map);
cpu_set(me, cpu_callout_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; per_cpu(cpu_state, me) = CPU_ONLINE;
} }
...@@ -1106,15 +1138,24 @@ void __init smp_cpus_done(unsigned int max_cpus) ...@@ -1106,15 +1138,24 @@ void __init smp_cpus_done(unsigned int max_cpus)
static void remove_siblinginfo(int cpu) static void remove_siblinginfo(int cpu)
{ {
int sibling; 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]) for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
cpu_clear(cpu, cpu_sibling_map[sibling]); 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_sibling_map[cpu]);
cpus_clear(cpu_core_map[cpu]); cpus_clear(cpu_core_map[cpu]);
phys_proc_id[cpu] = BAD_APICID; phys_proc_id[cpu] = BAD_APICID;
cpu_core_id[cpu] = BAD_APICID; cpu_core_id[cpu] = BAD_APICID;
cpu_clear(cpu, cpu_sibling_setup_map);
} }
void remove_cpu_from_maps(void) void remove_cpu_from_maps(void)
......
...@@ -65,7 +65,9 @@ struct cpuinfo_x86 { ...@@ -65,7 +65,9 @@ struct cpuinfo_x86 {
int f00f_bug; int f00f_bug;
int coma_bug; int coma_bug;
unsigned long loops_per_jiffy; 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))); } __attribute__((__aligned__(SMP_CACHE_BYTES)));
#define X86_VENDOR_INTEL 0 #define X86_VENDOR_INTEL 0
......
...@@ -61,10 +61,12 @@ struct cpuinfo_x86 { ...@@ -61,10 +61,12 @@ struct cpuinfo_x86 {
int x86_cache_alignment; int x86_cache_alignment;
int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/ int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/
__u8 x86_virt_bits, x86_phys_bits; __u8 x86_virt_bits, x86_phys_bits;
__u8 x86_num_cores; __u8 x86_max_cores; /* cpuid returned max cores value */
__u32 x86_power; __u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */ __u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy; unsigned long loops_per_jiffy;
__u8 apicid;
__u8 booted_cores; /* number of cores as seen by OS */
} ____cacheline_aligned; } ____cacheline_aligned;
#define X86_VENDOR_INTEL 0 #define X86_VENDOR_INTEL 0
......
...@@ -84,6 +84,16 @@ static __inline__ int get_bitmask_order(unsigned int count) ...@@ -84,6 +84,16 @@ static __inline__ int get_bitmask_order(unsigned int count)
return order; /* We could be slightly more clever with -1 here... */ 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 * hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word * of bits set) of a N-bit word
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment