Subject: Re: port-i386/19163: VIA C3 processor isn't recognized correctly
To: Takahiro Kambe <taca@back-street.net>
From: Bang Jun-Young <junyoung@netbsd.org>
List: netbsd-bugs
Date: 12/06/2002 10:13:20
On Thu, Dec 05, 2002 at 11:40:40PM +0900, Takahiro Kambe wrote:
> What's differ about "3DNOW" cpu feature?

Could you try with the following patch?

Index: i386/machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.500
diff -u -r1.500 machdep.c
--- i386/machdep.c	2002/12/05 16:19:08	1.500
+++ i386/machdep.c	2002/12/06 01:08:47
@@ -341,6 +341,7 @@
 void amd_family5_setup __P((struct cpu_info *));
 void transmeta_cpu_setup __P((struct cpu_info *));
 
+static void via_cpu_probe __P((struct cpu_info *));
 static void amd_family6_probe __P((struct cpu_info *));
 
 static void transmeta_cpu_info __P((struct cpu_info *));
@@ -792,8 +793,8 @@
 				"K5 or K6"		/* Default */
 			},
 			amd_family5_setup,
-			amd_cpuid_cpu_cacheinfo,
 			NULL,
+			amd_cpuid_cpu_cacheinfo,
 		},
 		/* Family 6 */
 		{
@@ -818,7 +819,7 @@
 				"Unknown K7 (Athlon)"	/* Default */
 			},
 			NULL,
-			amd_cpuid_cpu_cacheinfo,
+			NULL,
 			NULL,
 		} }
 	},
@@ -969,8 +970,8 @@
 				"C3"	/* Default */
 			},
 			NULL,
+			via_cpu_probe,
 			NULL,
-			NULL,
 		},
 		/* Family > 6, not yet available from VIA */
 		{
@@ -1098,6 +1099,29 @@
 	    : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)	\
 	    : "a" (code));
 
+void
+via_cpu_probe(struct cpu_info *ci)
+{
+	u_int descs[4];
+	u_int lfunc;
+
+	/*
+	 * Determine the largest extended function value.
+	 */
+	CPUID(0x80000000, descs[0], descs[1], descs[2], descs[3]);
+	lfunc = descs[0];
+
+	/*
+	 * Determine the extended feature flags.
+	 */
+	if (lfunc >= 0x80000001) {
+		CPUID(0x80000001, descs[0], descs[1], descs[2], descs[3]);
+		ci->ci_feature_flags = descs[3];
+		ci->ci_feature_str2 = CPUID_EXT_FLAGS2;
+		ci->ci_feature_str3 = CPUID_EXT_FLAGS3;
+	}
+}
+
 static void
 cpu_probe_base_features(struct cpu_info *ci)
 {
@@ -1121,6 +1145,14 @@
 
 	CPUID(1, ci->ci_signature, miscbytes, dummy1, ci->ci_feature_flags);
 
+	/*
+	 * These may be overridden with vendor specific strings in
+	 * (*ci_info)() later.
+	 */
+	ci->ci_feature_str1 = CPUID_FLAGS1;
+	ci->ci_feature_str2 = CPUID_FLAGS2;
+	ci->ci_feature_str3 = CPUID_FLAGS3;
+
 	/* Brand is low order 8 bits of ebx */
 	ci->ci_brand_id = miscbytes & 0xff;
 
@@ -1213,14 +1245,25 @@
 void
 amd_family6_probe(struct cpu_info *ci)
 {
-	u_int32_t eax;
-	u_int32_t dummy1, dummy2, dummy3;
+	u_int32_t lfunc;
+	u_int32_t descs[4];
 	u_int32_t brand[12];
 	char *p;
 	int i;
+
+	CPUID(0x80000000, lfunc, descs[1], descs[2], descs[3]);
+
+	/*
+	 * Determine the extended feature flags.
+	 */
+	if (lfunc >= 0x80000001) {
+		CPUID(0x80000001, descs[0], descs[1], descs[2], descs[3]);
+		ci->ci_feature_flags |= descs[3];
+		ci->ci_feature_str2 = CPUID_EXT_FLAGS2;
+		ci->ci_feature_str3 = CPUID_EXT_FLAGS3;
+	}
 
-	CPUID(0x80000000, eax, dummy1, dummy2, dummy3);
-	if (eax < 0x80000004)
+	if (lfunc < 0x80000004)
 		return;
 	
 	CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
@@ -1795,18 +1838,18 @@
 
 	if (ci->ci_feature_flags) {
 		if ((ci->ci_feature_flags & CPUID_MASK1) != 0) {
-			bitmask_snprintf(ci->ci_feature_flags, CPUID_FLAGS1,
-			    buf, sizeof(buf));
+			bitmask_snprintf(ci->ci_feature_flags,
+			    ci->ci_feature_str1, buf, sizeof(buf));
 			printf("%s: features %s\n", cpuname, buf);
 		}
 		if ((ci->ci_feature_flags & CPUID_MASK2) != 0) {
-			bitmask_snprintf(ci->ci_feature_flags, CPUID_FLAGS2,
-			    buf, sizeof(buf));
+			bitmask_snprintf(ci->ci_feature_flags,
+			    ci->ci_feature_str2, buf, sizeof(buf));
 			printf("%s: features %s\n", cpuname, buf);
 		}
 		if ((ci->ci_feature_flags & CPUID_MASK3) != 0) {
-			bitmask_snprintf(ci->ci_feature_flags, CPUID_FLAGS3,
-			    buf, sizeof(buf));
+			bitmask_snprintf(ci->ci_feature_flags,
+			    ci->ci_feature_str3, buf, sizeof(buf));
 			printf("%s: features %s\n", cpuname, buf);
 		}
 	}
Index: include/cpu.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/include/cpu.h,v
retrieving revision 1.90
diff -u -r1.90 cpu.h
--- include/cpu.h	2002/11/28 21:43:55	1.90
+++ include/cpu.h	2002/12/06 01:08:47
@@ -127,6 +127,9 @@
 	int32_t		ci_cpuid_level;
 	u_int32_t	ci_signature;	 /* X86 cpuid type */
 	u_int32_t	ci_feature_flags;/* X86 CPUID feature bits */
+	char *		ci_feature_str1; /* Vendor specific feature strings */
+	char *		ci_feature_str2;
+	char *		ci_feature_str3;
 	u_int32_t	ci_cpu_class;	 /* CPU class */
 	u_int32_t	ci_brand_id;	 /* Intel brand id */
 	u_int32_t	ci_vendor[4];	 /* vendor string */
Index: include/specialreg.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/include/specialreg.h,v
retrieving revision 1.25
diff -u -r1.25 specialreg.h
--- include/specialreg.h	2002/12/05 17:25:26	1.25
+++ include/specialreg.h	2002/12/06 01:08:47
@@ -133,6 +133,20 @@
 #define CPUID_FLAGS3	"\20\31FXSR\32SSE\33SSE2\34SS\35HTT\36TM\37B30\40SBF"
 #define CPUID_MASK3	0xff000000
 
+/*
+ * AMD/VIA processor specific flags.
+ */
+
+#define CPUID_MPC	0x00080000	/* Multiprocessing Capable */
+#define CPUID_MMXX	0x00400000	/* AMD MMX Extensions */
+#define CPUID_3DNOW2	0x40000000	/* 3DNow! Instruction Extension */
+#define CPUID_3DNOW	0x80000000	/* 3DNow! Instructions */
+
+#define CPUID_EXT_FLAGS2	"\20\16PGE\17MCA\20CMOV\21PAT\22PSE36\23PN" \
+				    "\24MPC\25B20\26B21\27MMXX\30MMX"
+#define CPUID_EXT_FLAGS3	"\20\31FXSR\32SSE\33B26\34B27\35B28\36B29" \
+				    "\0373DNOW2\0403DNOW"
+
 #define CPUID2FAMILY(cpuid)	(((cpuid) >> 8) & 15)
 #define CPUID2MODEL(cpuid)	(((cpuid) >> 4) & 15)
 #define CPUID2STEPPING(cpuid)	((cpuid) & 15)

Jun-Young

-- 
Bang Jun-Young <junyoung@netbsd.org>