Subject: CPUID patch for recent AMD processors
To: None <tech-kern@netbsd.org>
From: Bang Jun-Young <junyoung@mogua.com>
List: tech-kern
Date: 10/04/2002 12:08:13
--cNdxnHkX5QqsyA0e
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

The title says all. :-)

Before:
cpu0: AMD Athlon Model 6 (Palomino) (686-class), 1532.12 MHz

After:
cpu0: AMD Athlon XP 1800+ (686-class), 1532.12 MHz

And it should identify model 6 and 7 of Duron processors correctly,
which are currently misidentified as Athlon.

Any objections if I commit it?

Jun-Young

-- 
Bang Jun-Young <junyoung@mogua.com>

--cNdxnHkX5QqsyA0e
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="amdcpuid.diff"

Index: machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.485
diff -u -r1.485 machdep.c
--- arch/i386/i386/machdep.c	2002/10/03 19:39:51	1.485
+++ arch/i386/i386/machdep.c	2002/10/04 02:58:34
@@ -323,6 +323,19 @@
 	"Pentium 4"	    /* Intel (R) Pentium (R) 4 processor */
 };
 
+/*
+ * AMD processors don't have Brand IDs, so we need these names for probe.
+ */
+static const char * const amd_brand[] = {
+	"",
+	"Duron",	/* AMD Duron(tm) */
+	"MP",		/* AMD Athlon(tm) MP */
+	"XP",		/* AMD Athlon(tm) XP */
+	"4"		/* AMD Athlon(tm) 4 */
+};
+
+static char amd_brand_name[48];
+
 #ifdef COMPAT_NOMID
 static int exec_nomid	__P((struct proc *, struct exec_package *));
 #endif
@@ -332,6 +345,8 @@
 void amd_family5_setup __P((struct cpu_info *));
 void transmeta_cpu_setup __P((struct cpu_info *));
 
+static void amd_family6_probe __P((struct cpu_info *));
+
 static void transmeta_cpu_info __P((struct cpu_info *));
 static void amd_cpuid_cpu_cacheinfo __P((struct cpu_info *));
 
@@ -815,14 +830,13 @@
 			{
 				0, "Athlon Model 1", "Athlon Model 2",
 				"Duron", "Athlon Model 4 (Thunderbird)",
-				0, "Athlon Model 6 (Palomino)",
-				"Athlon Model 7 (Morgan)", 0, 0, 0, 0,
+				0, "Athlon", "Duron", "Athlon", 0, 0, 0,
 				0, 0, 0, 0,
 				"K7 (Athlon)"	/* Default */
 			},
 			NULL,
+			amd_family6_probe,
 			amd_cpuid_cpu_cacheinfo,
-			NULL,
 		},
 		/* Family > 6 */
 		{
@@ -1170,6 +1184,30 @@
 	(*cpup->cpu_family[i].cpu_probe)(ci);
 }
 
+void
+amd_family6_probe(struct cpu_info *ci)
+{
+	u_int32_t eax;
+	u_int32_t dummy1, dummy2, dummy3;
+	u_int32_t brand[12];
+	char *p;
+	int i;
+
+	CPUID(0x80000000, eax, dummy1, dummy2, dummy3);
+	if (eax < 0x80000004)
+		return;
+	
+	CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
+	CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
+	CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
+
+	for (i = 1; i < sizeof(amd_brand) / sizeof(amd_brand[0]); i++)
+		if ((p = strstr((char *)brand, amd_brand[i])) != NULL) {
+			ci->ci_brand_id = i;
+			strcpy(amd_brand_name, p);
+			break;
+		}
+}
 
 void
 amd_family5_setup(struct cpu_info *ci)
@@ -1665,6 +1703,19 @@
 			    model >= 8 && ci->ci_brand_id &&
 			    ci->ci_brand_id < 8)
 				brand = i386_intel_brand[ci->ci_brand_id];
+			
+			if (vendor == CPUVENDOR_AMD && family == 6 &&
+			    model >= 6) {
+				if (ci->ci_brand_id == 1)
+					/* 
+					 * It's Duron. We override the 
+					 * name, since it might have been 
+					 * misidentified as Athlon.
+					 */
+					name = amd_brand[ci->ci_brand_id];
+				else
+					brand = amd_brand_name;
+			}
 		}
 	}
 

Index: Makefile
===================================================================
RCS file: /cvsroot/syssrc/sys/lib/libkern/Makefile,v
retrieving revision 1.65
diff -u -r1.65 Makefile
--- lib/libkern/Makefile	2002/06/18 23:46:53	1.65
+++ lib/libkern/Makefile	2002/10/03 16:50:43
@@ -39,6 +39,10 @@
 SRCS+=	__cmsg_alignbytes.c inet_addr.c intoa.c md4c.c md5c.c sha1.c pmatch.c
 SRCS+=	_que.c arc4random.c
 
+.if (${MACHINE_ARCH} == "i386")
+SRCS+=	strstr.c
+.endif
+
 # Files to clean up
 CLEANFILES+= lib${LIB}.o lib${LIB}.po
 

--cNdxnHkX5QqsyA0e
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="strstr.c"

/*	$NetBSD: strstr.c,v 1.10 1999/09/20 04:39:48 lukem Exp $	*/

/*-
 * Copyright (c) 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Chris Torek.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: strstr.c,v 1.10 1999/09/20 04:39:48 lukem Exp $");
#endif
#endif /* LIBC_SCCS and not lint */

#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
#else
#include <lib/libkern/libkern.h>
#endif

/*
 * Find the first occurrence of find in s.
 */
char *
strstr(s, find)
	const char *s, *find;
{
	char c, sc;
	size_t len;

	if ((c = *find++) != 0) {
		len = strlen(find);
		do {
			do {
				if ((sc = *s++) == 0)
					return (char *)0;
			} while (sc != c);
		} while (strncmp(s, find, len) != 0);
		s--;
	}
	/* LINTED interface specification */
	return ((char *)s);
}

--cNdxnHkX5QqsyA0e--