Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -206,9 +206,9 @@ static void __init init_amd(struct cpuinfo_x86 *c)
	display_cacheinfo(c);

	if (cpuid_eax(0x80000000) >= 0x80000008) {
		c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
		if (c->x86_num_cores & (c->x86_num_cores - 1))
			c->x86_num_cores = 1;
		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 cpuinfo_x86 *c)
	 * 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
}
+14 −22
Original line number Diff line number Diff line
@@ -335,7 +335,7 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
	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 cpuinfo_x86 *c)
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]);
	}
+1 −1
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
	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);

+1 −1
Original line number Diff line number Diff line
@@ -307,7 +307,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
#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 "
+3 −4
Original line number Diff line number Diff line
@@ -94,12 +94,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
	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
	
Loading