Module Name:    src
Committed By:   pgoyette
Date:           Wed May 13 22:25:51 UTC 2009

Modified Files:
        src/sys/arch/x86/include: cacheinfo.h specialreg.h
        src/usr.sbin/cpuctl/arch: i386.c

Log Message:
1. Extend CPU probe of Intel processors to handle extended-models.  This
   allows us to properly identify new Intel 45nm processors, Core i7,
   Atom, and the 45nm Xeon MP.

2. Properly decode several new Intel cache descriptors, as listed in the
   most recent (March 2009) edition of Intel's Application Note 485.

3. Convert decode of the various features masks to use the newly added
   snprintb_m(3) routine.

Addresses my PR bin/41289
Addresses my PR bin/41290


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/x86/include/cacheinfo.h
cvs rdiff -u -r1.33 -r1.34 src/sys/arch/x86/include/specialreg.h
cvs rdiff -u -r1.17 -r1.18 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/sys/arch/x86/include/cacheinfo.h
diff -u src/sys/arch/x86/include/cacheinfo.h:1.10 src/sys/arch/x86/include/cacheinfo.h:1.11
--- src/sys/arch/x86/include/cacheinfo.h:1.10	Wed Apr 15 05:56:36 2009
+++ src/sys/arch/x86/include/cacheinfo.h	Wed May 13 22:25:51 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: cacheinfo.h,v 1.10 2009/04/15 05:56:36 lukem Exp $	*/
+/*	$NetBSD: cacheinfo.h,v 1.11 2009/05/13 22:25:51 pgoyette Exp $	*/
 
 #ifndef _X86_CACHEINFO_H_
 #define _X86_CACHEINFO_H_
@@ -199,6 +199,10 @@
 #define __CI_TBL(a,b,c,d,e,f) { a, b, c, d, e, f }
 #endif
 
+/*
+ * XXX Currently organized mostly by cache type, but would be
+ * XXX easier to maintain if it were in descriptor type order.
+ */
 #define INTEL_CACHE_INFO { \
 __CI_TBL(CAI_ITLB,     0x01,    4, 32,        4 * 1024, NULL), \
 __CI_TBL(CAI_ITLB,     0xb0,    4,128,        4 * 1024, NULL), \
@@ -211,14 +215,23 @@
 __CI_TBL(CAI_ITLB,     0x50, 0xff, 64,        4 * 1024, "4K/4M: 64 entries"), \
 __CI_TBL(CAI_ITLB,     0x51, 0xff, 64,        4 * 1024, "4K/4M: 128 entries"),\
 __CI_TBL(CAI_ITLB,     0x52, 0xff, 64,        4 * 1024, "4K/4M: 256 entries"),\
+__CI_TBL(CAI_ITLB,     0x55, 0xff, 64,        4 * 1024, "2M/4M: 7 entries"), \
+__CI_TBL(CAI_DTLB2,    0x56,    4, 16, 4 * 1024 * 1024, NULL), \
+__CI_TBL(CAI_DTLB2,    0x57,    4, 16,        4 * 1024, NULL), \
+__CI_TBL(CAI_DTLB,     0x5a, 0xff, 64,        4 * 1024, "2M/4M: 32 entries (L0)"), \
 __CI_TBL(CAI_DTLB,     0x5b, 0xff, 64,        4 * 1024, "4K/4M: 64 entries"), \
 __CI_TBL(CAI_DTLB,     0x5c, 0xff, 64,        4 * 1024, "4K/4M: 128 entries"),\
 __CI_TBL(CAI_DTLB,     0x5d, 0xff, 64,        4 * 1024, "4K/4M: 256 entries"),\
+__CI_TBL(CAI_ITLB,     0xb1,    4, 64,               0, "8 2M/4 4M entries"), \
+__CI_TBL(CAI_ITLB,     0xb2,    4, 64,        4 * 1024, NULL), \
 __CI_TBL(CAI_ICACHE,   0x06,    4,        8 * 1024, 32, NULL), \
 __CI_TBL(CAI_ICACHE,   0x08,    4,       16 * 1024, 32, NULL), \
+__CI_TBL(CAI_ICACHE,   0x09,    4,       32 * 1024, 64, NULL), \
 __CI_TBL(CAI_ICACHE,   0x30,    8,       32 * 1024, 64, NULL), \
 __CI_TBL(CAI_DCACHE,   0x0a,    2,        8 * 1024, 32, NULL), \
 __CI_TBL(CAI_DCACHE,   0x0c,    4,       16 * 1024, 32, NULL), \
+__CI_TBL(CAI_DCACHE,   0x0d,    4,       16 * 1024, 32, NULL), \
+__CI_TBL(CAI_L2CACHE,  0x21,    8,      256 * 1024, 64, NULL), /* L2 (MLC) */ \
 __CI_TBL(CAI_L2CACHE,  0x39,    4,      128 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x3a,    6,      192 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x3b,    2,      128 * 1024, 64, NULL), \
@@ -231,6 +244,9 @@
 __CI_TBL(CAI_L2CACHE,  0x43,    4,      512 * 1024, 32, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x44,    4, 1 * 1024 * 1024, 32, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x45,    4, 2 * 1024 * 1024, 32, NULL), \
+__CI_TBL(CAI_L2CACHE,  0x48,   12, 3 * 1024 * 1024, 64, NULL), \
+								\
+/* 0x49 Is L2 on Xeon MP (Failym 0f, Model 06), L3 otherwise */	\
 __CI_TBL(CAI_L2CACHE,  0x49,   16, 4 * 1024 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x4e,   24, 6 * 1024 * 1024, 64, NULL), \
 __CI_TBL(CAI_DCACHE,   0x60,    8,       16 * 1024, 64, NULL), \
@@ -255,6 +271,32 @@
 __CI_TBL(CAI_L2CACHE,  0x85,    8, 2 * 1024 * 1024, 32, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x86,    4,      512 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x87,    8, 1 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x22, 0xff,      512 * 1024, 64, "sectored, 4-way "), \
+__CI_TBL(CAI_L3CACHE,  0x23, 0xff, 1 * 1024 * 1024, 64, "sectored, 8-way "), \
+__CI_TBL(CAI_L3CACHE,  0x25, 0xff, 2 * 1024 * 1024, 64, "sectored, 8-way "), \
+__CI_TBL(CAI_L3CACHE,  0x29, 0xff, 4 * 1024 * 1024, 64, "sectored, 8-way "), \
+__CI_TBL(CAI_L3CACHE,  0x46,    4, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x47,    8, 8 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x49,   16, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4a,   12, 6 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4b,   16, 8 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4c,   12,12 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4d,   16,16 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd0,    4,      512 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd1,    4, 1 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd2,    4, 2 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd6,    8, 1 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd7,    8, 2 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd8,    8, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xdc,   12, 3 *  512 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xdd,   12, 3 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xde,   12, 6 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xe2,   16, 2 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xe3,   16, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xe4,   16, 8 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xea,   24,12 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xeb,   24,24 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xec,   24,24 * 1024 * 1024, 64, NULL), \
 __CI_TBL(0,               0,    0,               0,  0, NULL)  \
 }
 

Index: src/sys/arch/x86/include/specialreg.h
diff -u src/sys/arch/x86/include/specialreg.h:1.33 src/sys/arch/x86/include/specialreg.h:1.34
--- src/sys/arch/x86/include/specialreg.h:1.33	Thu Mar 12 09:08:40 2009
+++ src/sys/arch/x86/include/specialreg.h	Wed May 13 22:25:51 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: specialreg.h,v 1.33 2009/03/12 09:08:40 yamt Exp $	*/
+/*	$NetBSD: specialreg.h,v 1.34 2009/05/13 22:25:51 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -121,24 +121,27 @@
 #define	CPUID_IA64	0x40000000	/* IA-64 architecture */
 #define	CPUID_SBF	0x80000000	/* signal break on FERR */
 
-#define CPUID_FLAGS1	"\20\1FPU\2VME\3DE\4PSE\5TSC\6MSR\7PAE" \
-			    "\10MCE\11CX8\12APIC\13B10\14SEP\15MTRR"
-#define CPUID_MASK1	0x00001fff
-#define CPUID_FLAGS2	"\20\16PGE\17MCA\20CMOV\21PAT\22PSE36\23PN\24CFLUSH" \
-			    "\25B20\26DS\27ACPI\30MMX"
-#define CPUID_MASK2	0x00ffe000
-#define CPUID_FLAGS3	"\20\31FXSR\32SSE\33SSE2\34SS\35HTT\36TM\37IA64\40SBF"
-#define CPUID_MASK3	0xff000000
+#define CPUID_FLAGS1	"\20\1FPU\2VME\3DE\4PSE\5TSC\6MSR\7PAE\10MCE\11CX8" \
+			    "\12APIC\13B10\14SEP\15MTRR\16PGE\17MCA\20CMOV" \
+			    "\21PAT\22PSE36\23PN\24CFLUSH\25B20\26DS\27ACPI" \
+			    "\30MMX\31FXSR\32SSE\33SSE2\34SS\35HTT\36TM" \
+			    "\37IA64\40SBF"
 
 /*
- * CPUID Intel extended features
+ * CPUID Intel extended features - %EDX
  */
 #define CPUID_SYSCALL	0x00000800	/* SYSCALL/SYSRET */
 #define CPUID_XD	0x00100000	/* Execute Disable */
 #define CPUID_EM64T	0x20000000	/* Intel EM64T */
 
-#define CPUID_INTEL_MASK4	0x20100800
-#define CPUID_INTEL_FLAGS4	"\20\14SYSCALL/SYSRET\25XD\36EM64T"
+#define CPUID_INTEL_EXT_FLAGS	"\20\14SYSCALL/SYSRET\25XD\36EM64T"
+
+/*
+ * CPUID Intel extended features - %ECX
+ */
+#define	CPUID_LAHF	0x00000001	/* LAHF/SAHF in IA-32e mode, 64bit sub*/
+
+#define	CPUID_INTEL_FLAGS4	"\20\1LAHF"
 
 /*
  * AMD/VIA processor specific flags.
@@ -175,7 +178,6 @@
 #define CPUID_SKINIT	0x00001000	/* SKINIT */
 #define CPUID_WDT	0x00002000	/* watchdog timer support */
 
-#define CPUID_AMD_MASK4	0x00003fff
 #define CPUID_AMD_FLAGS4	"\20\1LAHF\2CMPLEGACY\3SVM\4EAPIC\5ALTMOVCR0" \
 				    "\6LZCNT\7SSE4A\10MISALIGNSSE" \
 				    "\0113DNOWPREFETCH\12OSVW\13IBS" \
@@ -204,8 +206,8 @@
 #define CPUID_APM_HWP	0x00000080	/* HW P-State control */
 #define CPUID_APM_TSC	0x00000100	/* TSC invariant */
 
-#define CPUID_APM_FLAGS			"\20\1TS\2FID\3VID\4TTP\5HTC\6STC\007100\10HWP\11TSC"
-
+#define CPUID_APM_FLAGS		"\20\1TS\2FID\3VID\4TTP\5HTC\6STC\007100" \
+				    "\10HWP\11TSC"
 
 /*
  * Centaur Extended Feature flags
@@ -246,9 +248,11 @@
 #define	CPUID2_X2APIC	0x00200000	/* xAPIC Extensions */
 #define	CPUID2_POPCNT	0x00800000	
 
-#define CPUID2_FLAGS "\20\1SSE3\3DTES64\4MONITOR\5DS-CPL\6VMX\7SMX\10EST" \
-			"\11TM2\12SSSE3\13CID\16CX16\17xTPR\20PDCM\23DCA" \
-			"\24SSE41\25SSE42\26X2APIC\30POPCNT"
+#define CPUID2_FLAGS1	"\20\1SSE3\2B01\3DTES64\4MONITOR\5DS-CPL\6VMX\7SMX" \
+			    "\10EST\11TM2\12SSE3\13CID\14B11\15B12\16CX16" \
+			    "\17xTPR\20PDCM\21B16\22B17\23DCA\24SSE41\25SSE42" \
+			    "\26X2APIC\27MOVBE\30POPCNT\31B24\32B25\33XSAVE" \
+			    "\34OSXSAVE\35B28\36B29\37B30\40B31"
 
 #define CPUID2FAMILY(cpuid)	(((cpuid) >> 8) & 0xf)
 #define CPUID2MODEL(cpuid)	(((cpuid) >> 4) & 0xf)

Index: src/usr.sbin/cpuctl/arch/i386.c
diff -u src/usr.sbin/cpuctl/arch/i386.c:1.17 src/usr.sbin/cpuctl/arch/i386.c:1.18
--- src/usr.sbin/cpuctl/arch/i386.c:1.17	Wed Apr 22 18:10:38 2009
+++ src/usr.sbin/cpuctl/arch/i386.c	Wed May 13 22:25:51 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386.c,v 1.17 2009/04/22 18:10:38 christos Exp $	*/
+/*	$NetBSD: i386.c,v 1.18 2009/05/13 22:25:51 pgoyette 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.17 2009/04/22 18:10:38 christos Exp $");
+__RCSID("$NetBSD: i386.c,v 1.18 2009/05/13 22:25:51 pgoyette Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -94,11 +94,13 @@
 	const char	*ci_dev;
 	int32_t		ci_cpuid_level;
 	uint32_t	ci_signature;	 /* X86 cpuid type */
-	uint32_t	ci_feature_flags;/* X86 %edx CPUID feature bits */
-	uint32_t	ci_feature2_flags;/* X86 %ecx CPUID feature bits */
-	uint32_t	ci_feature3_flags;/* X86 extended %edx feature bits */
-	uint32_t	ci_feature4_flags;/* X86 extended %ecx feature bits */
-	uint32_t	ci_padlock_flags;/* VIA PadLock feature bits */
+	uint32_t	ci_feat_val[5];	 /* X86 CPUID feature bits
+					  *	[0] basic features %edx
+					  *	[1] basic features %ecx
+					  *	[2] extended features %edx
+					  *	[3] extended features %ecx
+					  *	[4] VIA padlock features
+					  */
 	uint32_t	ci_cpu_class;	 /* CPU class */
 	uint32_t	ci_brand_id;	 /* Intel brand id */
 	uint32_t	ci_vendor[4];	 /* vendor string */
@@ -122,6 +124,10 @@
 	void (*cpu_info)(struct cpu_info *);
 };
 
+struct cpu_extend_nameclass {
+	int ext_model;
+	const char *cpu_models[CPU_MAXMODEL+1];
+};
 
 struct cpu_cpuid_nameclass {
 	const char *cpu_id;
@@ -133,6 +139,7 @@
 		void (*cpu_setup)(struct cpu_info *);
 		void (*cpu_probe)(struct cpu_info *);
 		void (*cpu_info)(struct cpu_info *);
+		struct cpu_extend_nameclass *cpu_extended_names;
 	} cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1];
 };
 
@@ -237,6 +244,21 @@
 	""
 };
 
+struct cpu_extend_nameclass intel_family6_ext_models[] = {
+	{ /* Extended models 1x */
+	  0x01, { NULL,			NULL,
+		  NULL,			NULL,
+		  NULL,			NULL,
+		  NULL,			NULL,
+		  NULL,			NULL,
+		  "Core i7 (Nehalem)",	NULL,
+		  "Atom",		"XeonMP (Nehalem)",
+		   NULL,		NULL} },
+	{ /* End of list */
+	  0x00, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+};
+
 const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
 	{
 		"GenuineIntel",
@@ -254,6 +276,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 5 */
 		{
@@ -269,6 +292,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 6 */
 		{
@@ -291,6 +315,7 @@
 			NULL,
 			intel_family_new_probe,
 			NULL,
+			&intel_family6_ext_models[0],
 		},
 		/* Family > 6 */
 		{
@@ -303,6 +328,7 @@
 			NULL,
 			intel_family_new_probe,
 			NULL,
+			NULL,
 		} }
 	},
 	{
@@ -324,6 +350,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 5 */
 		{
@@ -337,6 +364,7 @@
 			amd_family5_setup,
 			NULL,
 			amd_cpu_cacheinfo,
+			NULL,
 		},
 		/* Family 6 */
 		{
@@ -351,6 +379,7 @@
 			NULL,
 			amd_family6_probe,
 			amd_cpu_cacheinfo,
+			NULL,
 		},
 		/* Family > 6 */
 		{
@@ -363,6 +392,7 @@
 			NULL,
 			amd_family6_probe,
 			amd_cpu_cacheinfo,
+			NULL,
 		} }
 	},
 	{
@@ -381,6 +411,7 @@
 			cyrix6x86_cpu_setup, /* XXX ?? */
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 5 */
 		{
@@ -394,6 +425,7 @@
 			cyrix6x86_cpu_setup,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 6 */
 		{
@@ -406,6 +438,7 @@
 			cyrix6x86_cpu_setup,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family > 6 */
 		{
@@ -418,6 +451,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		} }
 	},
 	{	/* MediaGX is now owned by National Semiconductor */
@@ -435,6 +469,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 5: Geode family, formerly MediaGX */
 		{
@@ -448,6 +483,7 @@
 			cyrix6x86_cpu_setup,
 			NULL,
 			amd_cpu_cacheinfo,
+			NULL,
 		},
 		/* Family 6, not yet available from NSC */
 		{
@@ -460,6 +496,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family > 6, not yet available from NSC */
 		{
@@ -472,6 +509,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		} }
 	},
 	{
@@ -489,6 +527,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 5 */
 		{
@@ -501,6 +540,7 @@
 			winchip_cpu_setup,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 6, VIA acquired IDT Centaur design subsidiary */
 		{
@@ -514,6 +554,7 @@
 			NULL,
 			via_cpu_probe,
 			via_cpu_cacheinfo,
+			NULL,
 		},
 		/* Family > 6, not yet available from VIA */
 		{
@@ -526,6 +567,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		} }
 	},
 	{
@@ -543,6 +585,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family 5 */
 		{
@@ -555,6 +598,7 @@
 			NULL,
 			NULL,
 			transmeta_cpu_info,
+			NULL,
 		},
 		/* Family 6, not yet available from Transmeta */
 		{
@@ -567,6 +611,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		},
 		/* Family > 6, not yet available from Transmeta */
 		{
@@ -579,6 +624,7 @@
 			NULL,
 			NULL,
 			NULL,
+			NULL,
 		} }
 	}
 };
@@ -590,8 +636,8 @@
 static void
 disable_tsc(struct cpu_info *ci)
 {
-	if (ci->ci_feature_flags & CPUID_TSC) {
-		ci->ci_feature_flags &= ~CPUID_TSC;
+	if (ci->ci_feat_val[0] & CPUID_TSC) {
+		ci->ci_feat_val[0] &= ~CPUID_TSC;
 		aprint_error("WARNING: broken TSC disabled\n");
 	}
 }
@@ -640,7 +686,7 @@
 	 * 253668.pdf 7.10.2
 	 */
 
-	if ((ci->ci_feature_flags & CPUID_HTT) != 0) {
+	if ((ci->ci_feat_val[0] & CPUID_HTT) != 0) {
 		x86_cpuid(1, descs);
 		lp_max = (descs[1] >> 16) & 0xff;
 	}
@@ -692,7 +738,7 @@
 	 */
 	if (lfunc >= 0x80000001) {
 		x86_cpuid(0x80000001, descs);
-		ci->ci_feature3_flags |= descs[3];
+		ci->ci_feat_val[2] |= descs[3];
 	}
 
 	if (model < 0x9)
@@ -708,7 +754,7 @@
 	lfunc = descs[3];
 	if (model > 0x9 || stepping >= 8) {	/* ACE */
 		if (lfunc & CPUID_VIA_HAS_ACE) {
-			ci->ci_padlock_flags = lfunc;
+			ci->ci_feat_val[4] = lfunc;
 		}
 	}
 }
@@ -966,8 +1012,8 @@
 	x86_cpuid(1, descs);
 	ci->ci_signature = descs[0];
 	miscbytes = descs[1];
-	ci->ci_feature2_flags = descs[2];
-	ci->ci_feature_flags = descs[3];
+	ci->ci_feat_val[1] = descs[2];
+	ci->ci_feat_val[0] = descs[3];
 
 	/* Brand is low order 8 bits of ebx */
 	ci->ci_brand_id = miscbytes & 0xff;
@@ -1009,7 +1055,7 @@
 	 * If the processor serial number misfeature is present and supported,
 	 * extract it here.
 	 */
-	if ((ci->ci_feature_flags & CPUID_PN) != 0) {
+	if ((ci->ci_feat_val[0] & CPUID_PN) != 0) {
 		ci->ci_cpu_serial[0] = ci->ci_signature;
 		x86_cpuid(3, descs);
 		ci->ci_cpu_serial[2] = descs[2];
@@ -1065,7 +1111,8 @@
 	 */
 	if (descs[0] >= 0x80000001) {
 		x86_cpuid(0x80000001, descs);
-		ci->ci_feature3_flags |= descs[3];
+		ci->ci_feat_val[2] |= descs[3];
+		ci->ci_feat_val[3] |= descs[2];
 	}
 }
 
@@ -1083,8 +1130,8 @@
 	 */
 	if (descs[0] >= 0x80000001) {
 		x86_cpuid(0x80000001, descs);
-		ci->ci_feature3_flags |= descs[3]; /* %edx */
-		ci->ci_feature4_flags = descs[2]; /* %ecx */
+		ci->ci_feat_val[2] |= descs[3]; /* %edx */
+		ci->ci_feat_val[3] = descs[2]; /* %ecx */
 	}
 
 	if (*cpu_brand_string == '\0')
@@ -1110,8 +1157,9 @@
 		 * support for global PTEs, instead using bit 9 (APIC)
 		 * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
 		 */
-		if (ci->ci_feature_flags & CPUID_APIC)
-			ci->ci_feature_flags = (ci->ci_feature_flags & ~CPUID_APIC) | CPUID_PGE;
+		if (ci->ci_feat_val[0] & CPUID_APIC)
+			ci->ci_feat_val[0] =
+			    (ci->ci_feat_val[0] & ~CPUID_APIC) | CPUID_PGE;
 		/*
 		 * XXX But pmap_pg_g is already initialized -- need to kick
 		 * XXX the pmap somehow.  How does the MP branch do this?
@@ -1181,9 +1229,10 @@
 void
 identifycpu(const char *cpuname)
 {
-	const char *name, *modifier, *vendorname, *brand = "";
+	const char *name = "", *modifier, *vendorname, *brand = "";
 	int class = CPUCLASS_386, i, xmax;
-	int modif, family, model;
+	int modif, family, model, ext_model;
+	const struct cpu_extend_nameclass *modlist;
 	const struct cpu_cpuid_nameclass *cpup = NULL;
 	const struct cpu_cpuid_family *cpufam;
 	const char *feature_str[5];
@@ -1191,7 +1240,8 @@
 	extern int cpu;
 	extern int cpu_info_level;
 	size_t sz;
-	char buf[256];
+	char buf[512];
+	char *bp;
 
 	ci = &cistore;
 	memset(ci, 0, sizeof(*ci));
@@ -1217,6 +1267,7 @@
 		if (family < CPU_MINFAMILY)
 			errx(1, "identifycpu: strange family value");
 		model = CPUID2MODEL(ci->ci_signature);
+		ext_model = CPUID2EXTMODEL(ci->ci_signature);
 
 		for (i = 0; i < xmax; i++) {
 			if (!strncmp((char *)ci->ci_vendor,
@@ -1245,11 +1296,29 @@
 			if (family > CPU_MAXFAMILY) {
 				family = CPU_MAXFAMILY;
 				model = CPU_DEFMODEL;
-			} else if (model > CPU_MAXMODEL)
+			} else if (model > CPU_MAXMODEL) {
 				model = CPU_DEFMODEL;
+				ext_model = 0;
+			}
 			cpufam = &cpup->cpu_family[family - CPU_MINFAMILY];
-			name = cpufam->cpu_models[model];
-			if (name == NULL)
+			if (cpufam->cpu_extended_names == NULL ||
+			    ext_model == 0)
+				name = cpufam->cpu_models[model];
+			else {
+				/*
+				 * Scan list(s) of extended model names
+				 */
+				modlist = cpufam->cpu_extended_names;
+				while (modlist->ext_model != 0) {
+					if (modlist->ext_model == ext_model) {
+						name =
+						     modlist->cpu_models[model];
+						break;
+					}
+					modlist++;
+				}
+			}
+			if (name == NULL || *name == '\0')
 			    name = cpufam->cpu_models[CPU_DEFMODEL];
 			class = cpufam->cpu_class;
 			ci->ci_info = cpufam->cpu_info;
@@ -1324,70 +1393,53 @@
 	if (ci->ci_info)
 		(*ci->ci_info)(ci);
 
+	/*
+	 * display CPU feature flags
+	 */
+
+#define	MAX_FEATURE_LEN	60	/* XXX Need to find a better way to set this */
+
 	feature_str[0] = CPUID_FLAGS1;
-	feature_str[1] = CPUID_FLAGS2;
-	feature_str[2] = CPUID_FLAGS3;
+	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_EXT_FLAGS;
-		feature_str[4] = CPUID_AMD_FLAGS4;
+		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_CYRIX:
+		feature_str[4] = CPUID_FLAGS_PADLOCK;
+		/* FALLTHRU */
 	default:
-		feature_str[3] = CPUID_EXT_FLAGS;
 		break;
 	}
 	
-	if (ci->ci_feature_flags) {
-		if ((ci->ci_feature_flags & CPUID_MASK1) != 0) {
-			snprintb(buf, sizeof(buf), feature_str[0],
-			    ci->ci_feature_flags);
-			aprint_verbose("%s: features %s\n", cpuname, buf);
-		}
-		if ((ci->ci_feature_flags & CPUID_MASK2) != 0) {
-			snprintb(buf, sizeof(buf), feature_str[1],
-			    ci->ci_feature_flags);
-			aprint_verbose("%s: features %s\n", cpuname, buf);
-		}
-		if ((ci->ci_feature_flags & CPUID_MASK3) != 0) {
-			snprintb(buf, sizeof(buf), feature_str[2],
-			    ci->ci_feature_flags);
-			aprint_verbose("%s: features %s\n", cpuname, buf);
+	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 (ci->ci_feature2_flags) {
-		snprintb(buf, sizeof(buf), CPUID2_FLAGS, ci->ci_feature2_flags);
-		aprint_verbose("%s: features2 %s\n", cpuname, buf);
-	}
-
-	if (ci->ci_feature3_flags) {
-		snprintb(buf, sizeof(buf), feature_str[3],
-		    ci->ci_feature3_flags);
-		aprint_verbose("%s: features3 %s\n", cpuname, buf);
-	}
-
-	if (ci->ci_feature4_flags) {
-		snprintb(buf, sizeof(buf), feature_str[4],
-		    ci->ci_feature4_flags);
-		aprint_verbose("%s: features4 %s\n", cpuname, buf);
-	}
-
-	if (ci->ci_padlock_flags) {
-		snprintb(buf, sizeof(buf), CPUID_FLAGS_PADLOCK,
-		    ci->ci_padlock_flags);
-		aprint_verbose("%s: padlock features %s\n", cpuname, buf);
-	}
-
 	if (*cpu_brand_string != '\0')
 		aprint_normal("%s: \"%s\"\n", cpuname, cpu_brand_string);
 
 	x86_print_cacheinfo(ci);
 
-	if (ci->ci_cpuid_level >= 3 && (ci->ci_feature_flags & CPUID_PN)) {
+	if (ci->ci_cpuid_level >= 3 && (ci->ci_feat_val[0] & CPUID_PN)) {
 		aprint_verbose("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
 		    cpuname,
 		    ci->ci_cpu_serial[0] / 65536, ci->ci_cpu_serial[0] % 65536,
@@ -1427,7 +1479,7 @@
 	if (cpu_vendor == CPUVENDOR_AMD) {
 		powernow_probe(ci);
 
-		if ((ci->ci_feature3_flags & CPUID_SVM) != 0) {
+		if ((ci->ci_feat_val[3] & CPUID_SVM) != 0) {
 			uint32_t data[4];
 
 			x86_cpuid(0x8000000a, data);

Reply via email to