Module Name:    src
Committed By:   msaitoh
Date:           Mon Dec 23 11:17:20 UTC 2013

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

Log Message:
CPUID leaf 2 and 4 are only for Intel processors.


To generate a diff of this commit:
cvs rdiff -u -r1.51 -r1.52 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.51 src/usr.sbin/cpuctl/arch/i386.c:1.52
--- src/usr.sbin/cpuctl/arch/i386.c:1.51	Mon Dec 23 10:13:59 2013
+++ src/usr.sbin/cpuctl/arch/i386.c	Mon Dec 23 11:17:20 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386.c,v 1.51 2013/12/23 10:13:59 msaitoh Exp $	*/
+/*	$NetBSD: i386.c,v 1.52 2013/12/23 11:17:20 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.51 2013/12/23 10:13:59 msaitoh Exp $");
+__RCSID("$NetBSD: i386.c,v 1.52 2013/12/23 11:17:20 msaitoh Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -94,6 +94,7 @@ struct cpu_info {
 	const char	*ci_dev;
 	int32_t		ci_cpu_type;     /* for cpu's without cpuid */
 	int32_t		ci_cpuid_level;	 /* highest cpuid supported */
+	uint32_t	ci_cpuid_extlevel; /* highest cpuid extended func lv */
 	uint32_t	ci_signature;	 /* X86 cpuid type */
 	uint32_t	ci_family;	 /* from ci_signature */
 	uint32_t	ci_model;	 /* from ci_signature */
@@ -212,6 +213,7 @@ static void	powernow_probe(struct cpu_in
 static void	intel_family_new_probe(struct cpu_info *);
 static void	via_cpu_probe(struct cpu_info *);
 /* (Cache) Info functions */
+static void 	intel_cpu_cacheinfo(struct cpu_info *);
 static void 	amd_cpu_cacheinfo(struct cpu_info *);
 static void	via_cpu_cacheinfo(struct cpu_info *);
 static void	tmx86_get_longrun_status(u_int *, u_int *, u_int *);
@@ -285,7 +287,7 @@ const struct cpu_cpuid_nameclass i386_cp
 			"486",		/* Default */
 			NULL,
 			NULL,
-			NULL,
+			intel_cpu_cacheinfo,
 		},
 		/* Family 5 */
 		{
@@ -300,7 +302,7 @@ const struct cpu_cpuid_nameclass i386_cp
 			"Pentium",	/* Default */
 			NULL,
 			NULL,
-			NULL,
+			intel_cpu_cacheinfo,
 		},
 		/* Family 6 */
 		{
@@ -363,7 +365,7 @@ const struct cpu_cpuid_nameclass i386_cp
 			"Pentium Pro, II or III",	/* Default */
 			NULL,
 			intel_family_new_probe,
-			NULL,
+			intel_cpu_cacheinfo,
 		},
 		/* Family > 6 */
 		{
@@ -375,7 +377,7 @@ const struct cpu_cpuid_nameclass i386_cp
 			"Pentium 4",	/* Default */
 			NULL,
 			intel_family_new_probe,
-			NULL,
+			intel_cpu_cacheinfo,
 		} }
 	},
 	{
@@ -956,6 +958,103 @@ amd_family6_probe(struct cpu_info *ci)
 		}
 }
 
+static void
+intel_cpu_cacheinfo(struct cpu_info *ci)
+{
+	const struct x86_cache_info *cai;
+	u_int descs[4];
+	int iterations, i, j;
+	int type, level;
+	int ways, partitions, linesize, sets;
+	int caitype = -1;
+	int totalsize;
+	uint8_t desc;
+
+	/* Return if the cpu is old pre-cpuid instruction cpu */
+	if (ci->ci_cpu_type >= 0)
+		return;
+
+	if (ci->ci_cpuid_level < 2)
+		return;
+
+	/*
+	 * Parse the cache info from `cpuid leaf 2', if we have it.
+	 * XXX This is kinda ugly, but hey, so is the architecture...
+	 */
+	x86_cpuid(2, descs);
+	iterations = descs[0] & 0xff;
+	while (iterations-- > 0) {
+		for (i = 0; i < 4; i++) {
+			if (descs[i] & 0x80000000)
+				continue;
+			for (j = 0; j < 4; j++) {
+				if (i == 0 && j == 0)
+					continue;
+				desc = (descs[i] >> (j * 8)) & 0xff;
+				if (desc == 0)
+					continue;
+				cai = cache_info_lookup(intel_cpuid_cache_info,
+				    desc);
+				if (cai != NULL)
+					ci->ci_cinfo[cai->cai_index] = *cai;
+			}
+		}
+		x86_cpuid(2, descs);
+	}
+
+	if (ci->ci_cpuid_level < 4)
+		return;
+
+	/* Parse the cache info from `cpuid leaf 4', if we have it. */
+	for (i = 0; ; i++) {
+		x86_cpuid2(4, i, descs);
+		type = __SHIFTOUT(descs[0], CPUID_DCP_CACHETYPE);
+		if (type == CPUID_DCP_CACHETYPE_N)
+			break;
+		level = __SHIFTOUT(descs[0], CPUID_DCP_CACHELEVEL);
+		switch (level) {
+		case 1:
+			if (type == CPUID_DCP_CACHETYPE_I)
+				caitype = CAI_ICACHE;
+			else if (type == CPUID_DCP_CACHETYPE_D)
+				caitype = CAI_DCACHE;
+			else
+				caitype = -1;
+			break;
+		case 2:
+			if (type == CPUID_DCP_CACHETYPE_U)
+				caitype = CAI_L2CACHE;
+			else
+				caitype = -1;
+			break;
+		case 3:
+			if (type == CPUID_DCP_CACHETYPE_U)
+				caitype = CAI_L3CACHE;
+			else
+				caitype = -1;
+			break;
+		default:
+			caitype = -1;
+			break;
+		}
+		if (caitype == -1) {
+			printf("unknown cache level&type (%d & %d)\n",
+			    level, type);
+			continue;
+		}
+		ways = __SHIFTOUT(descs[1], CPUID_DCP_WAYS) + 1;
+		partitions =__SHIFTOUT(descs[1], CPUID_DCP_PARTITIONS)
+		    + 1;
+		linesize = __SHIFTOUT(descs[1], CPUID_DCP_LINESIZE)
+		    + 1;
+		sets = descs[2] + 1;
+		totalsize = ways * partitions * linesize * sets;
+		ci->ci_cinfo[caitype].cai_totalsize = totalsize;
+		ci->ci_cinfo[caitype].cai_associativity = ways;
+		ci->ci_cinfo[caitype].cai_linesize = linesize;
+	}
+}
+
 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = 
     AMD_L2CACHE_INFO;
 
@@ -1302,14 +1401,8 @@ transmeta_cpu_info(struct cpu_info *ci)
 static void
 cpu_probe_base_features(struct cpu_info *ci, const char *cpuname)
 {
-	const struct x86_cache_info *cai;
 	u_int descs[4];
-	int iterations, i, j;
-	int type, level;
-	int ways, partitions, linesize, sets;
-	int caitype = -1;
-	int totalsize;
-	uint8_t desc;
+	int i;
 	uint32_t brand[12];
 
 	memset(ci, 0, sizeof(*ci));
@@ -1341,11 +1434,22 @@ cpu_probe_base_features(struct cpu_info 
 	ci->ci_vendor[3] = 0;
 
 	/*
+	 * Fn8000_0000:
+	 * - Get cpuid extended function's max level.
+	 */
+	x86_cpuid(0x80000000, descs);
+	if (descs[0] >=  0x80000000)
+		ci->ci_cpuid_extlevel = descs[0];
+	else {
+		/* Set lower value than 0x80000000 */
+		ci->ci_cpuid_extlevel = 0;
+	}
+
+	/*
 	 * Fn8000_000[2-4]:
 	 * - Save brand string.
 	 */
-	x86_cpuid(0x80000000, brand);
-	if (brand[0] >= 0x80000004) {
+	if (ci->ci_cpuid_extlevel >= 0x80000004) {
 		x86_cpuid(0x80000002, brand);
 		x86_cpuid(0x80000003, brand + 4);
 		x86_cpuid(0x80000004, brand + 8);
@@ -1362,6 +1466,8 @@ cpu_probe_base_features(struct cpu_info 
 	 * Fn0000_0001:
 	 * - Get CPU family, model and stepping (from eax).
 	 * - Initial local APIC ID and brand ID (from ebx)
+	 * - CPUID2 (from ecx)
+	 * - CPUID (from edx)
 	 */
 	x86_cpuid(1, descs);
 	ci->ci_signature = descs[0];
@@ -1378,36 +1484,6 @@ cpu_probe_base_features(struct cpu_info 
 	ci->ci_feat_val[1] = descs[2];
 	ci->ci_feat_val[0] = descs[3];
 
-	if (ci->ci_cpuid_level < 2)
-		return;
-
-	/*
-	 * Parse the cache info from `cpuid leaf 2', if we have it.
-	 * XXX This is kinda ugly, but hey, so is the architecture...
-	 */
-
-	x86_cpuid(2, descs);
-
-	iterations = descs[0] & 0xff;
-	while (iterations-- > 0) {
-		for (i = 0; i < 4; i++) {
-			if (descs[i] & 0x80000000)
-				continue;
-			for (j = 0; j < 4; j++) {
-				if (i == 0 && j == 0)
-					continue;
-				desc = (descs[i] >> (j * 8)) & 0xff;
-				if (desc == 0)
-					continue;
-				cai = cache_info_lookup(intel_cpuid_cache_info,
-				    desc);
-				if (cai != NULL)
-					ci->ci_cinfo[cai->cai_index] = *cai;
-			}
-		}
-		x86_cpuid(2, descs);
-	}
-
 	if (ci->ci_cpuid_level < 3)
 		return;
 
@@ -1422,58 +1498,6 @@ cpu_probe_base_features(struct cpu_info 
 		ci->ci_cpu_serial[1] = descs[3];
 	}
 
-	if (ci->ci_cpuid_level < 4)
-		return;
-
-	/* Parse the cache info from `cpuid leaf 4', if we have it. */
-	for (i = 0; ; i++) {
-		x86_cpuid2(4, i, descs);
-		type = __SHIFTOUT(descs[0], CPUID_DCP_CACHETYPE);
-		if (type == CPUID_DCP_CACHETYPE_N)
-			break;
-		level = __SHIFTOUT(descs[0], CPUID_DCP_CACHELEVEL);
-		switch (level) {
-		case 1:
-			if (type == CPUID_DCP_CACHETYPE_I)
-				caitype = CAI_ICACHE;
-			else if (type == CPUID_DCP_CACHETYPE_D)
-				caitype = CAI_DCACHE;
-			else
-				caitype = -1;
-			break;
-		case 2:
-			if (type == CPUID_DCP_CACHETYPE_U)
-				caitype = CAI_L2CACHE;
-			else
-				caitype = -1;
-			break;
-		case 3:
-			if (type == CPUID_DCP_CACHETYPE_U)
-				caitype = CAI_L3CACHE;
-			else
-				caitype = -1;
-			break;
-		default:
-			caitype = -1;
-			break;
-		}
-		if (caitype == -1) {
-			printf("unknown cache level&type (%d & %d)\n",
-			    level, type);
-			continue;
-		}
-		ways = __SHIFTOUT(descs[1], CPUID_DCP_WAYS) + 1;
-		partitions =__SHIFTOUT(descs[1], CPUID_DCP_PARTITIONS)
-		    + 1;
-		linesize = __SHIFTOUT(descs[1], CPUID_DCP_LINESIZE)
-		    + 1;
-		sets = descs[2] + 1;
-		totalsize = ways * partitions * linesize * sets;
-		ci->ci_cinfo[caitype].cai_totalsize = totalsize;
-		ci->ci_cinfo[caitype].cai_associativity = ways;
-		ci->ci_cinfo[caitype].cai_linesize = linesize;
-	}
-
 	if (ci->ci_cpuid_level < 0xd)
 		return;
 

Reply via email to