Module Name:    src
Committed By:   msaitoh
Date:           Wed Nov 21 12:19:52 UTC 2018

Modified Files:
        src/usr.sbin/cpuctl/arch: i386.c

Log Message:
 Decode package, core and SMT id if CPUID 0x0b is available on Intel processor.
If the value is different from the kernel value, we should fix the kernel code.

TODO: Use 0x1f if it's available.


To generate a diff of this commit:
cvs rdiff -u -r1.87 -r1.88 src/usr.sbin/cpuctl/arch/i386.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/cpuctl/arch/i386.c
diff -u src/usr.sbin/cpuctl/arch/i386.c:1.87 src/usr.sbin/cpuctl/arch/i386.c:1.88
--- src/usr.sbin/cpuctl/arch/i386.c:1.87	Wed Nov 21 10:34:53 2018
+++ src/usr.sbin/cpuctl/arch/i386.c	Wed Nov 21 12:19:51 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386.c,v 1.87 2018/11/21 10:34:53 msaitoh Exp $	*/
+/*	$NetBSD: i386.c,v 1.88 2018/11/21 12:19:51 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: i386.c,v 1.87 2018/11/21 10:34:53 msaitoh Exp $");
+__RCSID("$NetBSD: i386.c,v 1.88 2018/11/21 12:19:51 msaitoh Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -1786,23 +1786,14 @@ print_bits(const char *cpuname, const ch
 }
 
 static void
-identifycpu_cpuids(struct cpu_info *ci)
+identifycpu_cpuids_intel_0x04(struct cpu_info *ci)
 {
-	const char *cpuname = ci->ci_dev;
 	u_int lp_max = 1;	/* logical processors per package */
 	u_int smt_max;		/* smt per core */
 	u_int core_max = 1;	/* core per package */
 	u_int smt_bits, core_bits;
 	uint32_t descs[4];
 
-	aprint_verbose("%s: Initial APIC ID %u\n", cpuname, ci->ci_initapicid);
-	ci->ci_packageid = ci->ci_initapicid;
-	ci->ci_coreid = 0;
-	ci->ci_smtid = 0;
-	if (cpu_vendor != CPUVENDOR_INTEL) {
-		return;
-	}
-
 	/*
 	 * 253668.pdf 7.10.2
 	 */
@@ -1811,32 +1802,110 @@ identifycpu_cpuids(struct cpu_info *ci)
 		x86_cpuid(1, descs);
 		lp_max = __SHIFTOUT(descs[1], CPUID_HTT_CORES);
 	}
-	if (ci->ci_cpuid_level >= 4) {
-		x86_cpuid2(4, 0, descs);
-		core_max = __SHIFTOUT(descs[0], CPUID_DCP_CORE_P_PKG) + 1;
-	}
+	x86_cpuid2(4, 0, descs);
+	core_max = __SHIFTOUT(descs[0], CPUID_DCP_CORE_P_PKG) + 1;
+
 	assert(lp_max >= core_max);
 	smt_max = lp_max / core_max;
 	smt_bits = ilog2(smt_max - 1) + 1;
 	core_bits = ilog2(core_max - 1) + 1;
-	if (smt_bits + core_bits) {
+
+	if (smt_bits + core_bits)
 		ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits);
+
+	if (core_bits)
+		ci->ci_coreid = __SHIFTOUT(ci->ci_initapicid,
+		    __BITS(smt_bits, smt_bits + core_bits - 1));
+
+	if (smt_bits)
+		ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid,
+		    __BITS((int)0, (int)(smt_bits - 1)));
+}
+
+static void
+identifycpu_cpuids_intel_0x0b(struct cpu_info *ci)
+{
+	const char *cpuname = ci->ci_dev;
+	u_int smt_bits, core_bits, core_shift = 0, pkg_shift = 0;
+	uint32_t descs[4];
+	int i;
+
+	x86_cpuid(0x0b, descs);
+	if (descs[1] == 0) {
+		identifycpu_cpuids_intel_0x04(ci);
+		return;
+	}
+
+	for (i = 0; ; i++) {
+		unsigned int shiftnum, lvltype;
+		x86_cpuid2(0x0b, i, descs);
+
+		/* On invalid level, (EAX and) EBX return 0 */
+		if (descs[1] == 0)
+			break;
+
+		shiftnum = __SHIFTOUT(descs[0], CPUID_TOP_SHIFTNUM);
+		lvltype = __SHIFTOUT(descs[2], CPUID_TOP_LVLTYPE);
+		switch (lvltype) {
+		case CPUID_TOP_LVLTYPE_SMT:
+			core_shift = shiftnum;
+			break;
+		case CPUID_TOP_LVLTYPE_CORE:
+			pkg_shift = shiftnum;
+			break;
+		case CPUID_TOP_LVLTYPE_INVAL:
+			aprint_verbose("%s: Invalid level type\n", cpuname);
+			break;
+		default:
+			aprint_verbose("%s: Unknown level type(%d) \n",
+			    cpuname, lvltype);
+			break;
+		}
 	}
+
+	assert(pkg_shift >= core_shift);
+	smt_bits = core_shift;
+	core_bits = pkg_shift - core_shift;
+
+	ci->ci_packageid = ci->ci_initapicid >> pkg_shift;
+
+	if (core_bits)
+		ci->ci_coreid = __SHIFTOUT(ci->ci_initapicid,
+		    __BITS(core_shift, pkg_shift - 1));
+
+	if (smt_bits)
+		ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid,
+		    __BITS((int)0, core_shift - 1));
+}
+
+static void
+identifycpu_cpuids_intel(struct cpu_info *ci)
+{
+	const char *cpuname = ci->ci_dev;
+
+	if (ci->ci_cpuid_level >= 0x0b)
+		identifycpu_cpuids_intel_0x0b(ci);
+	else if (ci->ci_cpuid_level >= 4)
+		identifycpu_cpuids_intel_0x04(ci);
+
 	aprint_verbose("%s: Cluster/Package ID %u\n", cpuname,
 	    ci->ci_packageid);
-	if (core_bits) {
-		u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1);
+	aprint_verbose("%s: Core ID %u\n", cpuname, ci->ci_coreid);
+	aprint_verbose("%s: SMT ID %u\n", cpuname, ci->ci_smtid);
+}
 
-		ci->ci_coreid =
-		    __SHIFTOUT(ci->ci_initapicid, core_mask);
-		aprint_verbose("%s: Core ID %u\n", cpuname, ci->ci_coreid);
-	}
-	if (smt_bits) {
-		u_int smt_mask = __BITS((int)0, (int)(smt_bits - 1));
+static void
+identifycpu_cpuids(struct cpu_info *ci)
+{
+	const char *cpuname = ci->ci_dev;
 
-		ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask);
-		aprint_verbose("%s: SMT ID %u\n", cpuname, ci->ci_smtid);
-	}
+	aprint_verbose("%s: Initial APIC ID %u\n", cpuname, ci->ci_initapicid);
+	ci->ci_packageid = ci->ci_initapicid;
+	ci->ci_coreid = 0;
+	ci->ci_smtid = 0;
+
+	if (cpu_vendor == CPUVENDOR_INTEL)
+		identifycpu_cpuids_intel(ci);
 }
 
 void

Reply via email to