svn commit: r191648 - in head/sys: amd64/amd64 amd64/include i386/i386 i386/include

Jeff Roberson jeff at FreeBSD.org
Wed Apr 29 06:54:41 UTC 2009


Author: jeff
Date: Wed Apr 29 06:54:40 2009
New Revision: 191648
URL: http://svn.freebsd.org/changeset/base/191648

Log:
   - Add support for cpuid leaf 0xb.  This allows us to determine the
     topology of nehalem/corei7 based systems.
   - Remove the cpu_cores/cpu_logical detection from identcpu.
   - Describe the layout of the system in cpu_mp_announce().
  
  Sponsored by:   Nokia

Modified:
  head/sys/amd64/amd64/identcpu.c
  head/sys/amd64/amd64/mp_machdep.c
  head/sys/amd64/include/smp.h
  head/sys/amd64/include/specialreg.h
  head/sys/i386/i386/identcpu.c
  head/sys/i386/i386/mp_machdep.c
  head/sys/i386/include/smp.h
  head/sys/i386/include/specialreg.h

Modified: head/sys/amd64/amd64/identcpu.c
==============================================================================
--- head/sys/amd64/amd64/identcpu.c	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/amd64/amd64/identcpu.c	Wed Apr 29 06:54:40 2009	(r191648)
@@ -106,9 +106,6 @@ static struct {
 	{ CENTAUR_VENDOR_ID,	CPU_VENDOR_CENTAUR },	/* CentaurHauls */
 };
 
-int cpu_cores;
-int cpu_logical;
-
 
 extern int pq_l2size;
 extern int pq_l2nways;
@@ -195,7 +192,6 @@ printcpuinfo(void)
 	    cpu_vendor_id == CPU_VENDOR_CENTAUR) {
 		printf("  Stepping = %u", cpu_id & 0xf);
 		if (cpu_high > 0) {
-			u_int cmp = 1, htt = 1;
 
 			/*
 			 * Here we should probably set up flags indicating
@@ -400,28 +396,6 @@ printcpuinfo(void)
 			if (tsc_is_invariant)
 				printf("\n  TSC: P-state invariant");
 
-			/*
-			 * If this CPU supports HTT or CMP then mention the
-			 * number of physical/logical cores it contains.
-			 */
-			if (cpu_feature & CPUID_HTT)
-				htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
-			if (cpu_vendor_id == CPU_VENDOR_AMD &&
-			    (amd_feature2 & AMDID2_CMP))
-				cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
-			else if (cpu_vendor_id == CPU_VENDOR_INTEL &&
-			    (cpu_high >= 4)) {
-				cpuid_count(4, 0, regs);
-				if ((regs[0] & 0x1f) != 0)
-					cmp = ((regs[0] >> 26) & 0x3f) + 1;
-			}
-			cpu_cores = cmp;
-			cpu_logical = htt / cmp;
-			if (cmp > 1)
-				printf("\n  Cores per package: %d", cmp);
-			if ((htt / cmp) > 1)
-				printf("\n  Logical CPUs per core: %d",
-				    cpu_logical);
 		}
 	}
 	/* Avoid ugly blank lines: only print newline when we have to. */

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/amd64/amd64/mp_machdep.c	Wed Apr 29 06:54:40 2009	(r191648)
@@ -160,6 +160,8 @@ int apic_cpuids[MAX_APIC_ID + 1];
 static volatile u_int cpu_ipi_pending[MAXCPU];
 
 static u_int boot_address;
+static int cpu_logical;
+static int cpu_cores;
 
 static void	assign_cpu_ids(void);
 static void	set_interrupt_apic_ids(void);
@@ -181,13 +183,142 @@ mem_range_AP_init(void)
 		mem_range_softc.mr_op->initAP(&mem_range_softc);
 }
 
-struct cpu_group *
-cpu_topo(void)
+static void
+topo_probe_0xb(void)
+{
+	int logical;
+	int p[4];
+	int bits;
+	int type;
+	int cnt;
+	int i;
+	int x;
+
+	/* We only support two levels for now. */
+	for (i = 0; i < 3; i++) {
+		cpuid_count(0x0B, i, p);
+		bits = p[0] & 0x1f;
+		logical = p[1] &= 0xffff;
+		type = (p[2] >> 8) & 0xff;
+		if (type == 0 || logical == 0)
+			break;
+		for (cnt = 0, x = 0; x <= MAX_APIC_ID; x++) {
+			if (!cpu_info[x].cpu_present ||
+			    cpu_info[x].cpu_disabled)
+				continue;
+			if (x >> bits == boot_cpu_id >> bits)
+				cnt++;
+		}
+		if (type == CPUID_TYPE_SMT)
+			cpu_logical = cnt;
+		else if (type == CPUID_TYPE_CORE)
+			cpu_cores = cnt;
+	}
+	if (cpu_logical == 0)
+		cpu_logical = 1;
+	cpu_cores /= cpu_logical;
+}
+
+static void
+topo_probe_0x4(void)
+{
+	u_int threads_per_cache, p[4];
+	u_int htt, cmp;
+	int i;
+
+	htt = cmp = 1;
+	/*
+	 * If this CPU supports HTT or CMP then mention the
+	 * number of physical/logical cores it contains.
+	 */
+	if (cpu_feature & CPUID_HTT)
+		htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
+	if (cpu_vendor_id == CPU_VENDOR_AMD && (amd_feature2 & AMDID2_CMP))
+		cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
+	else if (cpu_vendor_id == CPU_VENDOR_INTEL && (cpu_high >= 4)) {
+		cpuid_count(4, 0, p);
+		if ((p[0] & 0x1f) != 0)
+			cmp = ((p[0] >> 26) & 0x3f) + 1;
+	}
+	cpu_cores = cmp;
+	cpu_logical = htt / cmp;
+
+	/* Setup the initial logical CPUs info. */
+	if (cpu_feature & CPUID_HTT)
+		logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
+
+	/*
+	 * Work out if hyperthreading is *really* enabled.  This
+	 * is made really ugly by the fact that processors lie: Dual
+	 * core processors claim to be hyperthreaded even when they're
+	 * not, presumably because they want to be treated the same
+	 * way as HTT with respect to per-cpu software licensing.
+	 * At the time of writing (May 12, 2005) the only hyperthreaded
+	 * cpus are from Intel, and Intel's dual-core processors can be
+	 * identified via the "deterministic cache parameters" cpuid
+	 * calls.
+	 */
+	/*
+	 * First determine if this is an Intel processor which claims
+	 * to have hyperthreading support.
+	 */
+	if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
+		/*
+		 * If the "deterministic cache parameters" cpuid calls
+		 * are available, use them.
+		 */
+		if (cpu_high >= 4) {
+			/* Ask the processor about the L1 cache. */
+			for (i = 0; i < 1; i++) {
+				cpuid_count(4, i, p);
+				threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
+				if (hyperthreading_cpus < threads_per_cache)
+					hyperthreading_cpus = threads_per_cache;
+				if ((p[0] & 0x1f) == 0)
+					break;
+			}
+		}
+
+		/*
+		 * If the deterministic cache parameters are not
+		 * available, or if no caches were reported to exist,
+		 * just accept what the HTT flag indicated.
+		 */
+		if (hyperthreading_cpus == 0)
+			hyperthreading_cpus = logical_cpus;
+	}
+}
+
+static void
+topo_probe(void)
 {
+
+	logical_cpus = logical_cpus_mask = 0;
+	if (cpu_high >= 0xb)
+		topo_probe_0xb();
+	else if (cpu_high)
+		topo_probe_0x4();
 	if (cpu_cores == 0)
-		cpu_cores = 1;
+		cpu_cores = mp_ncpus;
 	if (cpu_logical == 0)
 		cpu_logical = 1;
+}
+
+struct cpu_group *
+cpu_topo(void)
+{
+	int cg_flags;
+
+	/*
+	 * Determine whether any threading flags are
+	 * necessry.
+	 */
+	if (cpu_logical > 1 && hyperthreading_cpus)
+		cg_flags = CG_FLAG_HTT;
+	else if (cpu_logical > 1)
+		cg_flags = CG_FLAG_SMT;
+	else
+		cg_flags = 0;
 	if (mp_ncpus % (cpu_cores * cpu_logical) != 0) {
 		printf("WARNING: Non-uniform processors.\n");
 		printf("WARNING: Using suboptimal topology.\n");
@@ -202,17 +333,17 @@ cpu_topo(void)
 	 * Only HTT no multi-core.
 	 */
 	if (cpu_logical > 1 && cpu_cores == 1)
-		return (smp_topo_1level(CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
+		return (smp_topo_1level(CG_SHARE_L1, cpu_logical, cg_flags));
 	/*
 	 * Only multi-core no HTT.
 	 */
 	if (cpu_cores > 1 && cpu_logical == 1)
-		return (smp_topo_1level(CG_SHARE_NONE, cpu_cores, 0));
+		return (smp_topo_1level(CG_SHARE_L2, cpu_cores, cg_flags));
 	/*
 	 * Both HTT and multi-core.
 	 */
-	return (smp_topo_2level(CG_SHARE_NONE, cpu_cores,
-	    CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
+	return (smp_topo_2level(CG_SHARE_L2, cpu_cores,
+	    CG_SHARE_L1, cpu_logical, cg_flags));
 }
 
 /*
@@ -318,7 +449,6 @@ void
 cpu_mp_start(void)
 {
 	int i;
-	u_int threads_per_cache, p[4];
 
 	/* Initialize the logical ID to APIC ID table. */
 	for (i = 0; i < MAXCPU; i++) {
@@ -355,51 +485,8 @@ cpu_mp_start(void)
 		KASSERT(boot_cpu_id == PCPU_GET(apic_id),
 		    ("BSP's APIC ID doesn't match boot_cpu_id"));
 
-	/* Setup the initial logical CPUs info. */
-	logical_cpus = logical_cpus_mask = 0;
-	if (cpu_feature & CPUID_HTT)
-		logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
-
-	/*
-	 * Work out if hyperthreading is *really* enabled.  This
-	 * is made really ugly by the fact that processors lie: Dual
-	 * core processors claim to be hyperthreaded even when they're
-	 * not, presumably because they want to be treated the same
-	 * way as HTT with respect to per-cpu software licensing.
-	 * At the time of writing (May 12, 2005) the only hyperthreaded
-	 * cpus are from Intel, and Intel's dual-core processors can be
-	 * identified via the "deterministic cache parameters" cpuid
-	 * calls.
-	 */
-	/*
-	 * First determine if this is an Intel processor which claims
-	 * to have hyperthreading support.
-	 */
-	if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
-		/*
-		 * If the "deterministic cache parameters" cpuid calls
-		 * are available, use them.
-		 */
-		if (cpu_high >= 4) {
-			/* Ask the processor about the L1 cache. */
-			for (i = 0; i < 1; i++) {
-				cpuid_count(4, i, p);
-				threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
-				if (hyperthreading_cpus < threads_per_cache)
-					hyperthreading_cpus = threads_per_cache;
-				if ((p[0] & 0x1f) == 0)
-					break;
-			}
-		}
-
-		/*
-		 * If the deterministic cache parameters are not
-		 * available, or if no caches were reported to exist,
-		 * just accept what the HTT flag indicated.
-		 */
-		if (hyperthreading_cpus == 0)
-			hyperthreading_cpus = logical_cpus;
-	}
+	/* Probe logical/physical core configuration. */
+	topo_probe();
 
 	assign_cpu_ids();
 
@@ -419,6 +506,14 @@ cpu_mp_announce(void)
 	const char *hyperthread;
 	int i;
 
+	printf("FreeBSD/SMP: %d package(s) x %d core(s)",
+	    mp_ncpus / (cpu_cores * cpu_logical), cpu_cores);
+	if (hyperthreading_cpus > 1)
+	    printf(" x %d HTT threads", cpu_logical);
+	else if (cpu_logical > 1)
+	    printf(" x %d SMT threads", cpu_logical);
+	printf("\n");
+
 	/* List active CPUs first. */
 	printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
 	for (i = 1; i < mp_ncpus; i++) {

Modified: head/sys/amd64/include/smp.h
==============================================================================
--- head/sys/amd64/include/smp.h	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/amd64/include/smp.h	Wed Apr 29 06:54:40 2009	(r191648)
@@ -36,10 +36,6 @@ extern int			boot_cpu_id;
 extern struct pcb		stoppcbs[];
 extern int			cpu_apic_ids[];
 
-/* global data in identcpu.c */
-extern int			cpu_cores;
-extern int			cpu_logical;
-
 /* IPI handlers */
 inthand_t
 	IDTVEC(invltlb),	/* TLB shootdowns - global */

Modified: head/sys/amd64/include/specialreg.h
==============================================================================
--- head/sys/amd64/include/specialreg.h	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/amd64/include/specialreg.h	Wed Apr 29 06:54:40 2009	(r191648)
@@ -183,6 +183,13 @@
 #define	CPUID_HTT_CORES		0x00ff0000
 #define	CPUID_LOCAL_APIC_ID	0xff000000
 
+/* 
+ * CPUID instruction 0xb ebx info.
+ */
+#define	CPUID_TYPE_INVAL	0
+#define	CPUID_TYPE_SMT		1
+#define	CPUID_TYPE_CORE		2
+
 /*
  * AMD extended function 8000_0007h edx info
  */

Modified: head/sys/i386/i386/identcpu.c
==============================================================================
--- head/sys/i386/i386/identcpu.c	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/i386/i386/identcpu.c	Wed Apr 29 06:54:40 2009	(r191648)
@@ -159,9 +159,6 @@ static struct {
 #endif
 };
 
-int cpu_cores;
-int cpu_logical;
-
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
 int has_f00f_bug = 0;		/* Initialized so that it can be patched. */
 #endif
@@ -690,7 +687,6 @@ printcpuinfo(void)
 		if (cpu_vendor_id == CPU_VENDOR_CYRIX)
 			printf("  DIR=0x%04x", cyrix_did);
 		if (cpu_high > 0) {
-			u_int cmp = 1, htt = 1;
 
 			/*
 			 * Here we should probably set up flags indicating
@@ -895,28 +891,6 @@ printcpuinfo(void)
 			if (tsc_is_invariant)
 				printf("\n  TSC: P-state invariant");
 
-			/*
-			 * If this CPU supports HTT or CMP then mention the
-			 * number of physical/logical cores it contains.
-			 */
-			if (cpu_feature & CPUID_HTT)
-				htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
-			if (cpu_vendor_id == CPU_VENDOR_AMD &&
-			    (amd_feature2 & AMDID2_CMP))
-				cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
-			else if (cpu_vendor_id == CPU_VENDOR_INTEL &&
-			    (cpu_high >= 4)) {
-				cpuid_count(4, 0, regs);
-				if ((regs[0] & 0x1f) != 0)
-					cmp = ((regs[0] >> 26) & 0x3f) + 1;
-			}
-			cpu_cores = cmp;
-			cpu_logical = htt / cmp;
-			if (cmp > 1)
-				printf("\n  Cores per package: %d", cmp);
-			if ((htt / cmp) > 1)
-				printf("\n  Logical CPUs per core: %d",
-				    cpu_logical);
 		}
 	} else if (cpu_vendor_id == CPU_VENDOR_CYRIX) {
 		printf("  DIR=0x%04x", cyrix_did);

Modified: head/sys/i386/i386/mp_machdep.c
==============================================================================
--- head/sys/i386/i386/mp_machdep.c	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/i386/i386/mp_machdep.c	Wed Apr 29 06:54:40 2009	(r191648)
@@ -213,6 +213,8 @@ int apic_cpuids[MAX_APIC_ID + 1];
 static volatile u_int cpu_ipi_pending[MAXCPU];
 
 static u_int boot_address;
+static int cpu_logical;
+static int cpu_cores;
 
 static void	assign_cpu_ids(void);
 static void	install_ap_tramp(void);
@@ -234,13 +236,142 @@ mem_range_AP_init(void)
 		mem_range_softc.mr_op->initAP(&mem_range_softc);
 }
 
-struct cpu_group *
-cpu_topo(void)
+static void
+topo_probe_0xb(void)
+{
+	int logical;
+	int p[4];
+	int bits;
+	int type;
+	int cnt;
+	int i;
+	int x;
+
+	/* We only support two levels for now. */
+	for (i = 0; i < 3; i++) {
+		cpuid_count(0x0B, i, p);
+		bits = p[0] & 0x1f;
+		logical = p[1] &= 0xffff;
+		type = (p[2] >> 8) & 0xff;
+		if (type == 0 || logical == 0)
+			break;
+		for (cnt = 0, x = 0; x <= MAX_APIC_ID; x++) {
+			if (!cpu_info[x].cpu_present ||
+			    cpu_info[x].cpu_disabled)
+				continue;
+			if (x >> bits == boot_cpu_id >> bits)
+				cnt++;
+		}
+		if (type == CPUID_TYPE_SMT)
+			cpu_logical = cnt;
+		else if (type == CPUID_TYPE_CORE)
+			cpu_cores = cnt;
+	}
+	if (cpu_logical == 0)
+		cpu_logical = 1;
+	cpu_cores /= cpu_logical;
+}
+
+static void
+topo_probe_0x4(void)
+{
+	u_int threads_per_cache, p[4];
+	u_int htt, cmp;
+	int i;
+
+	htt = cmp = 1;
+	/*
+	 * If this CPU supports HTT or CMP then mention the
+	 * number of physical/logical cores it contains.
+	 */
+	if (cpu_feature & CPUID_HTT)
+		htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
+	if (cpu_vendor_id == CPU_VENDOR_AMD && (amd_feature2 & AMDID2_CMP))
+		cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
+	else if (cpu_vendor_id == CPU_VENDOR_INTEL && (cpu_high >= 4)) {
+		cpuid_count(4, 0, p);
+		if ((p[0] & 0x1f) != 0)
+			cmp = ((p[0] >> 26) & 0x3f) + 1;
+	}
+	cpu_cores = cmp;
+	cpu_logical = htt / cmp;
+
+	/* Setup the initial logical CPUs info. */
+	if (cpu_feature & CPUID_HTT)
+		logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
+
+	/*
+	 * Work out if hyperthreading is *really* enabled.  This
+	 * is made really ugly by the fact that processors lie: Dual
+	 * core processors claim to be hyperthreaded even when they're
+	 * not, presumably because they want to be treated the same
+	 * way as HTT with respect to per-cpu software licensing.
+	 * At the time of writing (May 12, 2005) the only hyperthreaded
+	 * cpus are from Intel, and Intel's dual-core processors can be
+	 * identified via the "deterministic cache parameters" cpuid
+	 * calls.
+	 */
+	/*
+	 * First determine if this is an Intel processor which claims
+	 * to have hyperthreading support.
+	 */
+	if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
+		/*
+		 * If the "deterministic cache parameters" cpuid calls
+		 * are available, use them.
+		 */
+		if (cpu_high >= 4) {
+			/* Ask the processor about the L1 cache. */
+			for (i = 0; i < 1; i++) {
+				cpuid_count(4, i, p);
+				threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
+				if (hyperthreading_cpus < threads_per_cache)
+					hyperthreading_cpus = threads_per_cache;
+				if ((p[0] & 0x1f) == 0)
+					break;
+			}
+		}
+
+		/*
+		 * If the deterministic cache parameters are not
+		 * available, or if no caches were reported to exist,
+		 * just accept what the HTT flag indicated.
+		 */
+		if (hyperthreading_cpus == 0)
+			hyperthreading_cpus = logical_cpus;
+	}
+}
+
+static void
+topo_probe(void)
 {
+
+	logical_cpus = logical_cpus_mask = 0;
+	if (cpu_high >= 0xb)
+		topo_probe_0xb();
+	else if (cpu_high)
+		topo_probe_0x4();
 	if (cpu_cores == 0)
-		cpu_cores = 1;
+		cpu_cores = mp_ncpus;
 	if (cpu_logical == 0)
 		cpu_logical = 1;
+}
+
+struct cpu_group *
+cpu_topo(void)
+{
+	int cg_flags;
+
+	/*
+	 * Determine whether any threading flags are
+	 * necessry.
+	 */
+	if (cpu_logical > 1 && hyperthreading_cpus)
+		cg_flags = CG_FLAG_HTT;
+	else if (cpu_logical > 1)
+		cg_flags = CG_FLAG_SMT;
+	else
+		cg_flags = 0;
 	if (mp_ncpus % (cpu_cores * cpu_logical) != 0) {
 		printf("WARNING: Non-uniform processors.\n");
 		printf("WARNING: Using suboptimal topology.\n");
@@ -255,17 +386,17 @@ cpu_topo(void)
 	 * Only HTT no multi-core.
 	 */
 	if (cpu_logical > 1 && cpu_cores == 1)
-		return (smp_topo_1level(CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
+		return (smp_topo_1level(CG_SHARE_L1, cpu_logical, cg_flags));
 	/*
 	 * Only multi-core no HTT.
 	 */
 	if (cpu_cores > 1 && cpu_logical == 1)
-		return (smp_topo_1level(CG_SHARE_NONE, cpu_cores, 0));
+		return (smp_topo_1level(CG_SHARE_L2, cpu_cores, cg_flags));
 	/*
 	 * Both HTT and multi-core.
 	 */
-	return (smp_topo_2level(CG_SHARE_NONE, cpu_cores,
-	    CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
+	return (smp_topo_2level(CG_SHARE_L2, cpu_cores,
+	    CG_SHARE_L1, cpu_logical, cg_flags));
 }
 
 
@@ -354,7 +485,6 @@ void
 cpu_mp_start(void)
 {
 	int i;
-	u_int threads_per_cache, p[4];
 
 	/* Initialize the logical ID to APIC ID table. */
 	for (i = 0; i < MAXCPU; i++) {
@@ -399,51 +529,8 @@ cpu_mp_start(void)
 		KASSERT(boot_cpu_id == PCPU_GET(apic_id),
 		    ("BSP's APIC ID doesn't match boot_cpu_id"));
 
-	/* Setup the initial logical CPUs info. */
-	logical_cpus = logical_cpus_mask = 0;
-	if (cpu_feature & CPUID_HTT)
-		logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
-
-	/*
-	 * Work out if hyperthreading is *really* enabled.  This
-	 * is made really ugly by the fact that processors lie: Dual
-	 * core processors claim to be hyperthreaded even when they're
-	 * not, presumably because they want to be treated the same
-	 * way as HTT with respect to per-cpu software licensing.
-	 * At the time of writing (May 12, 2005) the only hyperthreaded
-	 * cpus are from Intel, and Intel's dual-core processors can be
-	 * identified via the "deterministic cache parameters" cpuid
-	 * calls.
-	 */
-	/*
-	 * First determine if this is an Intel processor which claims
-	 * to have hyperthreading support.
-	 */
-	if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
-		/*
-		 * If the "deterministic cache parameters" cpuid calls
-		 * are available, use them.
-		 */
-		if (cpu_high >= 4) {
-			/* Ask the processor about the L1 cache. */
-			for (i = 0; i < 1; i++) {
-				cpuid_count(4, i, p);
-				threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
-				if (hyperthreading_cpus < threads_per_cache)
-					hyperthreading_cpus = threads_per_cache;
-				if ((p[0] & 0x1f) == 0)
-					break;
-			}
-		}
-
-		/*
-		 * If the deterministic cache parameters are not
-		 * available, or if no caches were reported to exist,
-		 * just accept what the HTT flag indicated.
-		 */
-		if (hyperthreading_cpus == 0)
-			hyperthreading_cpus = logical_cpus;
-	}
+	/* Probe logical/physical core configuration. */
+	topo_probe();
 
 	assign_cpu_ids();
 
@@ -463,6 +550,14 @@ cpu_mp_announce(void)
 	const char *hyperthread;
 	int i;
 
+	printf("FreeBSD/SMP: %d package(s) x %d core(s)",
+	    mp_ncpus / (cpu_cores * cpu_logical), cpu_cores);
+	if (hyperthreading_cpus > 1)
+	    printf(" x %d HTT threads", cpu_logical);
+	else if (cpu_logical > 1)
+	    printf(" x %d SMT threads", cpu_logical);
+	printf("\n");
+
 	/* List active CPUs first. */
 	printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
 	for (i = 1; i < mp_ncpus; i++) {

Modified: head/sys/i386/include/smp.h
==============================================================================
--- head/sys/i386/include/smp.h	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/i386/include/smp.h	Wed Apr 29 06:54:40 2009	(r191648)
@@ -45,10 +45,6 @@ extern u_long *ipi_rendezvous_counts[MAX
 extern u_long *ipi_lazypmap_counts[MAXCPU];
 #endif
 
-/* global data in identcpu.c */
-extern int			cpu_cores;
-extern int			cpu_logical;
-
 /* IPI handlers */
 inthand_t
 	IDTVEC(invltlb),	/* TLB shootdowns - global */

Modified: head/sys/i386/include/specialreg.h
==============================================================================
--- head/sys/i386/include/specialreg.h	Wed Apr 29 06:52:04 2009	(r191647)
+++ head/sys/i386/include/specialreg.h	Wed Apr 29 06:54:40 2009	(r191648)
@@ -182,6 +182,13 @@
 #define	CPUID_HTT_CORES		0x00ff0000
 #define	CPUID_LOCAL_APIC_ID	0xff000000
 
+/* 
+ * CPUID instruction 0xb ebx info.
+ */
+#define	CPUID_TYPE_INVAL	0
+#define	CPUID_TYPE_SMT		1
+#define	CPUID_TYPE_CORE		2
+
 /*
  * AMD extended function 8000_0007h edx info
  */


More information about the svn-src-head mailing list