Module Name:    src
Committed By:   dsl
Date:           Mon Jan  7 23:20:42 UTC 2013

Modified Files:
        src/usr.sbin/cpuctl/arch: cpuctl_i386.h i386-asm.S i386.c x86_64-asm.S

Log Message:
Add support for the xsave related data from cpuid 8.n.
Reorder the output so that the 'brand' string - which actually identifies
  the cpu is output first.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/cpuctl/arch/cpuctl_i386.h
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/cpuctl/arch/i386-asm.S
cvs rdiff -u -r1.37 -r1.38 src/usr.sbin/cpuctl/arch/i386.c
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/cpuctl/arch/x86_64-asm.S

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/cpuctl_i386.h
diff -u src/usr.sbin/cpuctl/arch/cpuctl_i386.h:1.1 src/usr.sbin/cpuctl/arch/cpuctl_i386.h:1.2
--- src/usr.sbin/cpuctl/arch/cpuctl_i386.h:1.1	Sat Jan  5 15:27:45 2013
+++ src/usr.sbin/cpuctl/arch/cpuctl_i386.h	Mon Jan  7 23:20:42 2013
@@ -1,4 +1,4 @@
-/*      $NetBSD: cpuctl_i386.h,v 1.1 2013/01/05 15:27:45 dsl Exp $      */
+/*      $NetBSD: cpuctl_i386.h,v 1.2 2013/01/07 23:20:42 dsl Exp $      */
 
 /* Interfaces to code in i386-asm.S */
 
@@ -6,3 +6,4 @@
 
 void x86_cpuid2(uint32_t, uint32_t, uint32_t *);
 uint32_t x86_identify(void);
+uint32_t x86_xgetbv(void);

Index: src/usr.sbin/cpuctl/arch/i386-asm.S
diff -u src/usr.sbin/cpuctl/arch/i386-asm.S:1.2 src/usr.sbin/cpuctl/arch/i386-asm.S:1.3
--- src/usr.sbin/cpuctl/arch/i386-asm.S:1.2	Sat Jan  5 15:27:45 2013
+++ src/usr.sbin/cpuctl/arch/i386-asm.S	Mon Jan  7 23:20:42 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386-asm.S,v 1.2 2013/01/05 15:27:45 dsl Exp $	*/
+/*	$NetBSD: i386-asm.S,v 1.3 2013/01/07 23:20:42 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000, 2004, 2006, 2007 The NetBSD Foundation, Inc.
@@ -48,6 +48,11 @@ ENTRY(x86_cpuid2)
 	ret
 END(x86_cpuid2)
 
+ENTRY(x86_xgetbv)
+	xgetbv
+	ret
+END(x86_xgetbv)
+
 ENTRY(x86_identify)
 	/* Try to toggle alignment check flag; does not exist on 386. */
 	pushfl

Index: src/usr.sbin/cpuctl/arch/i386.c
diff -u src/usr.sbin/cpuctl/arch/i386.c:1.37 src/usr.sbin/cpuctl/arch/i386.c:1.38
--- src/usr.sbin/cpuctl/arch/i386.c:1.37	Sun Jan  6 23:17:35 2013
+++ src/usr.sbin/cpuctl/arch/i386.c	Mon Jan  7 23:20:42 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386.c,v 1.37 2013/01/06 23:17:35 dsl Exp $	*/
+/*	$NetBSD: i386.c,v 1.38 2013/01/07 23:20:42 dsl 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.37 2013/01/06 23:17:35 dsl Exp $");
+__RCSID("$NetBSD: i386.c,v 1.38 2013/01/07 23:20:42 dsl Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -97,12 +97,14 @@ struct cpu_info {
 	uint32_t	ci_signature;	 /* X86 cpuid type */
 	uint32_t	ci_family;	 /* from ci_signature */
 	uint32_t	ci_model;	 /* from ci_signature */
-	uint32_t	ci_feat_val[5];	 /* X86 CPUID feature bits
+	uint32_t	ci_feat_val[8];	 /* X86 CPUID feature bits
 					  *	[0] basic features %edx
 					  *	[1] basic features %ecx
 					  *	[2] extended features %edx
 					  *	[3] extended features %ecx
 					  *	[4] VIA padlock features
+					  *	[5] XCR0 bits (d:0 %eax)
+					  *	[6] xsave flags (d:1 %eax)
 					  */
 	uint32_t	ci_cpu_class;	 /* CPU class */
 	uint32_t	ci_brand_id;	 /* Intel brand id */
@@ -113,6 +115,10 @@ struct cpu_info {
 	uint8_t		ci_coreid;
 	uint8_t		ci_smtid;
 	uint32_t	ci_initapicid;
+
+	uint32_t	ci_cur_xsave;
+	uint32_t	ci_max_xsave;
+
 	struct x86_cache_info ci_cinfo[CAI_COUNT];
 	void		(*ci_info)(struct cpu_info *);
 };
@@ -204,11 +210,6 @@ static void amd_family5_setup(struct cpu
 static void powernow_probe(struct cpu_info *);
 
 /*
- * Info for CTL_HW
- */
-static char	cpu_model[120];
-
-/*
  * Note: these are just the ones that may not have a cpuid instruction.
  * We deal with the rest in a different way.
  */
@@ -999,6 +1000,19 @@ cpu_probe_base_features(struct cpu_info 
 		ci->ci_cpu_serial[2] = descs[2];
 		ci->ci_cpu_serial[1] = descs[3];
 	}
+
+	if (ci->ci_cpuid_level < 0xd)
+		return;
+
+	/* Get support XRC0 bits */
+	x86_cpuid2(0xd, 0, descs);
+	ci->ci_feat_val[5] = descs[0];	/* Actually 64 bits */
+	ci->ci_cur_xsave = descs[1];
+	ci->ci_max_xsave = descs[2];
+
+	/* Additional flags (eg xsaveopt support) */
+	x86_cpuid2(0xd, 1, descs);
+	ci->ci_feat_val[6] = descs[0];   /* Actually 64 bits */
 }
 
 static void
@@ -1159,6 +1173,26 @@ transmeta_cpu_info(struct cpu_info *ci)
 	}
 }
 
+static void
+print_bits(const char *cpuname, const char *hdr, const char *fmt, uint32_t val)
+{
+	char buf[32 * 16];
+	char *bp;
+
+#define	MAX_LINE_LEN	79	/* get from command arg or 'stty cols' ? */
+
+	if (val == 0 || fmt == NULL)
+		return;
+
+	snprintb_m(buf, sizeof(buf), fmt, val,
+	    MAX_LINE_LEN - strlen(cpuname) - 2 - strlen(hdr) - 1);
+	bp = buf;
+	while (*bp != '\0') {
+		aprint_verbose("%s: %s %s\n", cpuname, hdr, bp);
+		bp += strlen(bp) + 1;
+	}
+}
+
 void
 identifycpu(int fd, const char *cpuname)
 {
@@ -1168,11 +1202,8 @@ identifycpu(int fd, const char *cpuname)
 	int modif, family;
 	const struct cpu_cpuid_nameclass *cpup = NULL;
 	const struct cpu_cpuid_family *cpufam;
-	const char *feature_str[5];
 	struct cpu_info *ci, cistore;
 	size_t sz;
-	char buf[512];
-	char *bp;
 	struct cpu_ucode_version ucode;
 	union {
 		struct cpu_ucode_version_amd amd;
@@ -1279,20 +1310,31 @@ identifycpu(int fd, const char *cpuname)
 	(void)sysctlbyname("machdep.pae", &use_pae, &sz, NULL, 0);
 	largepagesize = (use_pae ? 2 * 1024 * 1024 : 4 * 1024 * 1024);
 
-	snprintf(cpu_model, sizeof(cpu_model), "%s%s%s%s%s%s%s (%s-class)",
-	    vendorname,
-	    *modifier ? " " : "", modifier,
-	    *name ? " " : "", name,
-	    *brand ? " " : "", brand,
-	    classnames[class]);
-	aprint_normal("%s: %s", cpuname, cpu_model);
+	/*
+	 * The 'cpu_brand_string' is much more useful than the 'cpu_model'
+	 * we try to determine from the family/model values.
+	 */
+	if (*cpu_brand_string != '\0')
+		aprint_normal("%s: \"%s\"\n", cpuname, cpu_brand_string);
+
+	aprint_normal("%s: %s", cpuname, vendorname);
+	if (*modifier)
+		aprint_normal(" %s", modifier);
+	if (*name)
+		aprint_normal(" %s", name);
+	if (*brand)
+		aprint_normal(" %s", brand);
+	aprint_normal(" (%s-class)", classnames[class]);
 
 	if (ci->ci_tsc_freq != 0)
-		aprint_normal(", %ju.%02ju MHz",
+		aprint_normal(", %ju.%02ju MHz\n",
 		    ((uintmax_t)ci->ci_tsc_freq + 4999) / 1000000,
 		    (((uintmax_t)ci->ci_tsc_freq + 4999) / 10000) % 100);
+
+	aprint_normal_dev(ci->ci_dev, "family %#x model %#x stepping %#x",
+	    ci->ci_family, ci->ci_model, CPUID2STEPPING(ci->ci_signature));
 	if (ci->ci_signature != 0)
-		aprint_normal(", id 0x%x", ci->ci_signature);
+		aprint_normal(" (id %#x)", ci->ci_signature);
 	aprint_normal("\n");
 
 	if (ci->ci_info)
@@ -1302,45 +1344,33 @@ identifycpu(int fd, const char *cpuname)
 	 * display CPU feature flags
 	 */
 
-#define	MAX_FEATURE_LEN	60	/* XXX Need to find a better way to set this */
+	print_bits(cpuname, "features", CPUID_FLAGS1, ci->ci_feat_val[0]);
+	print_bits(cpuname, "features1", CPUID2_FLAGS1, ci->ci_feat_val[1]);
 
-	feature_str[0] = CPUID_FLAGS1;
-	feature_str[1] = CPUID2_FLAGS1;
-	feature_str[2] = CPUID_EXT_FLAGS;
-	feature_str[3] = NULL;
-	feature_str[4] = NULL;
-
-	switch (cpu_vendor) {
-	case CPUVENDOR_AMD:
-		feature_str[3] = CPUID_AMD_FLAGS4;
-		break;
-	case CPUVENDOR_INTEL:
-		feature_str[2] = CPUID_INTEL_EXT_FLAGS;
-		feature_str[3] = CPUID_INTEL_FLAGS4;
-		break;
-	case CPUVENDOR_IDT:
-		feature_str[4] = CPUID_FLAGS_PADLOCK;
-		break;
-	default:
-		break;
+	/* These next two are actually common definitions! */
+	print_bits(cpuname, "features2",
+	    cpu_vendor == CPUVENDOR_INTEL ? CPUID_INTEL_EXT_FLAGS
+		: CPUID_EXT_FLAGS, ci->ci_feat_val[2]);
+	print_bits(cpuname, "features3",
+	    cpu_vendor == CPUVENDOR_INTEL ? CPUID_INTEL_FLAGS4
+		: CPUID_AMD_FLAGS4, ci->ci_feat_val[3]);
+
+	print_bits(cpuname, "padloack features", CPUID_FLAGS_PADLOCK,
+	    ci->ci_feat_val[4]);
+
+	print_bits(cpuname, "xsave features", XCR0_FLAGS1, ci->ci_feat_val[5]);
+	print_bits(cpuname, "xsave instructions", CPUID_PES1_FLAGS,
+	    ci->ci_feat_val[6]);
+
+	if (ci->ci_max_xsave != 0) {
+		aprint_normal("%s: xsave area size: current %d, maximum %d",
+			cpuname, ci->ci_cur_xsave, ci->ci_max_xsave);
+		aprint_normal(", xgetbv %sabled\n",
+		    ci->ci_feat_val[1] & CPUID2_OSXSAVE ? "en" : "dis");
+		if (ci->ci_feat_val[1] & CPUID2_OSXSAVE)
+			print_bits(cpuname, "enabled xsave", XCR0_FLAGS1,
+			    x86_xgetbv());
 	}
-	
-	for (i = 0; i <= 4; i++) {
-		if (ci->ci_feat_val[i] && feature_str[i] != NULL) {
-			snprintb_m(buf, sizeof(buf), feature_str[i],
-				   ci->ci_feat_val[i], MAX_FEATURE_LEN);
-			bp = buf;
-			while (*bp != '\0') {
-				aprint_verbose("%s: %sfeatures%c %s\n",
-				    cpuname, (i == 4)?"padlock ":"", 
-				    (i == 4 || i == 0)?' ':'1' + i, bp);
-				bp += strlen(bp) + 1;
-			}
-		}
-	}
-
-	if (*cpu_brand_string != '\0')
-		aprint_normal("%s: \"%s\"\n", cpuname, cpu_brand_string);
 
 	x86_print_cacheinfo(ci);
 
@@ -1390,19 +1420,12 @@ identifycpu(int fd, const char *cpuname)
 
 		if ((data[0] >= 0x8000000a)
 		   && (ci->ci_feat_val[3] & CPUID_SVM) != 0) {
-
 			x86_cpuid(0x8000000a, data);
 			aprint_verbose("%s: SVM Rev. %d\n", cpuname,
 			    data[0] & 0xf);
 			aprint_verbose("%s: SVM NASID %d\n", cpuname, data[1]);
-			snprintb_m(buf, sizeof(buf), CPUID_AMD_SVM_FLAGS,
-				   data[3], MAX_FEATURE_LEN);
-			bp = buf;
-			while (*bp != '\0') {
-				aprint_verbose("%s: SVM features %s\n",
-				    cpuname, bp);
-				bp += strlen(bp) + 1;
-			}
+			print_bits(cpuname, "SVM features", CPUID_AMD_SVM_FLAGS,
+				   data[3]);
 		}
 	}
 
@@ -1410,9 +1433,6 @@ identifycpu(int fd, const char *cpuname)
 	clockmod_init();
 #endif
 
-	aprint_normal_dev(ci->ci_dev, "family %02x model %02x stepping %02x\n",
-	    ci->ci_family, ci->ci_model, CPUID2STEPPING(ci->ci_signature));
-
 	if (cpu_vendor == CPUVENDOR_AMD)
 		ucode.loader_version = CPU_UCODE_LOADER_AMD;
 	else if (cpu_vendor == CPUVENDOR_INTEL)

Index: src/usr.sbin/cpuctl/arch/x86_64-asm.S
diff -u src/usr.sbin/cpuctl/arch/x86_64-asm.S:1.3 src/usr.sbin/cpuctl/arch/x86_64-asm.S:1.4
--- src/usr.sbin/cpuctl/arch/x86_64-asm.S:1.3	Sat Jan  5 15:33:00 2013
+++ src/usr.sbin/cpuctl/arch/x86_64-asm.S	Mon Jan  7 23:20:42 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_64-asm.S,v 1.3 2013/01/05 15:33:00 dsl Exp $	*/
+/*	$NetBSD: x86_64-asm.S,v 1.4 2013/01/07 23:20:42 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -43,6 +43,10 @@ ENTRY(x86_cpuid2)
 	popq	%rbx
 	ret
 
+ENTRY(x86_xgetbv)
+	xgetbv
+	ret
+
 ENTRY(x86_identify)
 	movl	$-1,%eax
 	ret

Reply via email to