Commit 3dd9d514 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds
Browse files

[PATCH] x86_64: add support for Intel dual-core detection and displaying

Appended patch adds the support for Intel dual-core detection and displaying
the core related information in /proc/cpuinfo.  

It adds two new fields "core id" and "cpu cores" to x86 /proc/cpuinfo and the
"core id" field for x86_64("cpu cores" field is already present in x86_64).

Number of processor cores in a die is detected using cpuid(4) and this is
documented in IA-32 Intel Architecture Software Developer's Manual (vol 2a)
(http://developer.intel.com/design/pentium4/manuals/index_new.htm#sdm_vol2a

)

This patch also adds cpu_core_map similar to cpu_sibling_map.

Slightly hacked by AK.

Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f2ea2750
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -188,6 +188,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
	}

	display_cacheinfo(c);

	if (cpuid_eax(0x80000000) >= 0x80000008) {
		c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
		if (c->x86_num_cores & (c->x86_num_cores - 1))
			c->x86_num_cores = 1;
	}

	detect_ht(c);

#ifdef CONFIG_X86_HT
@@ -199,12 +206,6 @@ static void __init init_amd(struct cpuinfo_x86 *c)
	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
		smp_num_siblings = 1;
#endif

	if (cpuid_eax(0x80000000) >= 0x80000008) {
		c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
		if (c->x86_num_cores & (c->x86_num_cores - 1))
			c->x86_num_cores = 1;
	}
}

static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+20 −8
Original line number Diff line number Diff line
@@ -434,7 +434,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
void __init detect_ht(struct cpuinfo_x86 *c)
{
	u32 	eax, ebx, ecx, edx;
	int 	index_lsb, index_msb, tmp;
	int 	index_msb, tmp;
	int 	cpu = smp_processor_id();

	if (!cpu_has(c, X86_FEATURE_HT))
@@ -446,7 +446,6 @@ void __init detect_ht(struct cpuinfo_x86 *c)
	if (smp_num_siblings == 1) {
		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
	} else if (smp_num_siblings > 1 ) {
		index_lsb = 0;
		index_msb = 31;

		if (smp_num_siblings > NR_CPUS) {
@@ -455,21 +454,34 @@ void __init detect_ht(struct cpuinfo_x86 *c)
			return;
		}
		tmp = smp_num_siblings;
		while ((tmp & 1) == 0) {
			tmp >>=1 ;
			index_lsb++;
		}
		tmp = smp_num_siblings;
		while ((tmp & 0x80000000 ) == 0) {
			tmp <<=1 ;
			index_msb--;
		}
		if (index_lsb != index_msb )
		if (smp_num_siblings & (smp_num_siblings - 1))
			index_msb++;
		phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);

		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
		       phys_proc_id[cpu]);

		smp_num_siblings = smp_num_siblings / c->x86_num_cores;

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

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

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

		if (c->x86_num_cores > 1)
			printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
			       cpu_core_id[cpu]);
	}
}
#endif
+23 −0
Original line number Diff line number Diff line
@@ -77,6 +77,27 @@ static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c)
}


/*
 * find out the number of processor cores on the die
 */
static int __init num_cpu_cores(struct cpuinfo_x86 *c)
{
	unsigned int eax;

	if (c->cpuid_level < 4)
		return 1;

	__asm__("cpuid"
		: "=a" (eax)
		: "0" (4), "c" (0)
		: "bx", "dx");

	if (eax & 0x1f)
		return ((eax >> 26) + 1);
	else
		return 1;
}

static void __init init_intel(struct cpuinfo_x86 *c)
{
	unsigned int l2 = 0;
@@ -139,6 +160,8 @@ static void __init init_intel(struct cpuinfo_x86 *c)
	if ( p )
		strcpy(c->x86_model_id, p);
	
	c->x86_num_cores = num_cpu_cores(c);

	detect_ht(c);

	/* Work around errata */
+8 −0
Original line number Diff line number Diff line
@@ -129,6 +129,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
	seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
		     c->loops_per_jiffy/(500000/HZ),
		     (c->loops_per_jiffy/(5000/HZ)) % 100);

#ifdef CONFIG_SMP
	/* Put new fields at the end to lower the probability of
	   breaking user space parsers. */
	seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]);
	seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
#endif

	return 0;
}

+29 −2
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ static int __initdata smp_b_stepping;
int smp_num_siblings = 1;
int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
EXPORT_SYMBOL(phys_proc_id);
int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
EXPORT_SYMBOL(cpu_core_id);

/* bitmap of online cpus */
cpumask_t cpu_online_map;
@@ -885,6 +887,7 @@ static int boot_cpu_logical_apicid;
void *xquad_portio;

cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;

static void __init smp_boot_cpus(unsigned int max_cpus)
{
@@ -907,6 +910,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
	cpus_clear(cpu_sibling_map[0]);
	cpu_set(0, cpu_sibling_map[0]);

	cpus_clear(cpu_core_map[0]);
	cpu_set(0, cpu_core_map[0]);

	/*
	 * If we couldn't find an SMP configuration at boot time,
	 * get out of here now!
@@ -919,6 +925,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
			printk(KERN_NOTICE "Local APIC not detected."
					   " Using dummy APIC emulation.\n");
		map_cpu_to_logical_apicid();
		cpu_set(0, cpu_sibling_map[0]);
		cpu_set(0, cpu_core_map[0]);
		return;
	}

@@ -942,6 +950,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
		smpboot_clear_io_apic_irqs();
		phys_cpu_present_map = physid_mask_of_physid(0);
		cpu_set(0, cpu_sibling_map[0]);
		cpu_set(0, cpu_core_map[0]);
		return;
	}

@@ -955,6 +965,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
		smpboot_clear_io_apic_irqs();
		phys_cpu_present_map = physid_mask_of_physid(0);
		cpu_set(0, cpu_sibling_map[0]);
		cpu_set(0, cpu_core_map[0]);
		return;
	}

@@ -1035,10 +1047,13 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
	 * construct cpu_sibling_map[], so that we can tell sibling CPUs
	 * efficiently.
	 */
	for (cpu = 0; cpu < NR_CPUS; cpu++)
	for (cpu = 0; cpu < NR_CPUS; cpu++) {
		cpus_clear(cpu_sibling_map[cpu]);
		cpus_clear(cpu_core_map[cpu]);
	}

	for (cpu = 0; cpu < NR_CPUS; cpu++) {
		struct cpuinfo_x86 *c = cpu_data + cpu;
		int siblings = 0;
		int i;
		if (!cpu_isset(cpu, cpu_callout_map))
@@ -1048,7 +1063,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
			for (i = 0; i < NR_CPUS; i++) {
				if (!cpu_isset(i, cpu_callout_map))
					continue;
				if (phys_proc_id[cpu] == phys_proc_id[i]) {
				if (cpu_core_id[cpu] == cpu_core_id[i]) {
					siblings++;
					cpu_set(i, cpu_sibling_map[cpu]);
				}
@@ -1060,6 +1075,18 @@ static void __init smp_boot_cpus(unsigned int max_cpus)

		if (siblings != smp_num_siblings)
			printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);

		if (c->x86_num_cores > 1) {
			for (i = 0; i < NR_CPUS; i++) {
				if (!cpu_isset(i, cpu_callout_map))
					continue;
				if (phys_proc_id[cpu] == phys_proc_id[i]) {
					cpu_set(i, cpu_core_map[cpu]);
				}
			}
		} else {
			cpu_core_map[cpu] = cpu_sibling_map[cpu];
		}
	}

	if (nmi_watchdog == NMI_LOCAL_APIC)
Loading