Module Name:    src
Committed By:   snj
Date:           Fri Jan 16 08:30:51 UTC 2015

Modified Files:
        src/usr.sbin/cpuctl [netbsd-6]: cpuctl.8 cpuctl.c cpuctl.h
        src/usr.sbin/cpuctl/arch [netbsd-6]: i386-asm.S i386.c x86_64-asm.S

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #1230):
        usr.sbin/cpuctl/cpuctl.8: revisions 1.9-1.12
        usr.sbin/cpuctl/cpuctl.c: revisions 1.22-1.23 and 1.25 via patch
        usr.sbin/cpuctl/cpuctl.h: revision 1.5 via patch
        usr.sbin/cpuctl/arch/cpuctl_i386.h: revisions 1.1-1.2
        usr.sbin/cpuctl/arch/i386-asm.S: revisions 1.2-1.3
        usr.sbin/cpuctl/arch/i386.c: revisions 1.34, 1.36-1.49, 1.51-1.63 via 
patch
        usr.sbin/cpuctl/arch/x86_64-asm.S: revisions 1.3-1.4
Update cpuctl(8). Microcode and ARM related changes are not included:
- Change the i386 asm x86_identify() so it returns a value instead of
  writing into global data. Fix a stack alignment fubar that would
  cause a crash on a cirix 486. Refactor identify code to common setup
  for normal identify and ucode identify - which was missing a
  memset().
- The Intel and AMD docs (more or less) agree on how the cpuid
  'extended family' and 'extended model' bits are used to create
  larger values than the original 16bit value allowed for.
  Calculate and save these values 'up-front' and use them throughout.
  Untangle the (backwards) nested switch statement for amd 'model 15'
  cpus.
- Use full model number to index name strings - a lot of 256 element
  arrays don't matter in usespace.
- 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.
- Only complain about binding if we have more than 1 cpu.
- Check cpuid leaf 4 for newer Intel CPU to know the cache information.
- Support prefetch size.
- Print the highest extended info level as the basic info level.
- Update URL of AMD's web page.
- Add code to detect hypervisor. The code was based from FreeBSD and
  ported by Kengo Nakahara.
- Add verbose flag.
- Add newline if ci_tsc_freq is 0 to not to break the output.
- Update Intel's processor family names and models.
- Print some more bits.
- Add shared TLB
- Add prototypes.
- Add comments.
- Make some functions static.
- Sort functions.
- KNF.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.8.2.1 src/usr.sbin/cpuctl/cpuctl.8
cvs rdiff -u -r1.20 -r1.20.2.1 src/usr.sbin/cpuctl/cpuctl.c
cvs rdiff -u -r1.2 -r1.2.10.1 src/usr.sbin/cpuctl/cpuctl.h
cvs rdiff -u -r1.1 -r1.1.24.1 src/usr.sbin/cpuctl/arch/i386-asm.S
cvs rdiff -u -r1.27.2.4 -r1.27.2.5 src/usr.sbin/cpuctl/arch/i386.c
cvs rdiff -u -r1.2 -r1.2.20.1 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/cpuctl.8
diff -u src/usr.sbin/cpuctl/cpuctl.8:1.8 src/usr.sbin/cpuctl/cpuctl.8:1.8.2.1
--- src/usr.sbin/cpuctl/cpuctl.8:1.8	Sat Jan 14 00:59:56 2012
+++ src/usr.sbin/cpuctl/cpuctl.8	Fri Jan 16 08:30:50 2015
@@ -1,4 +1,4 @@
-.\"	$NetBSD: cpuctl.8,v 1.8 2012/01/14 00:59:56 wiz Exp $
+.\"	$NetBSD: cpuctl.8,v 1.8.2.1 2015/01/16 08:30:50 snj Exp $
 .\"
 .\" Copyright (c) 2007, 2008, 2012 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 13, 2012
+.Dd December 23, 2013
 .Dt CPUCTL 8
 .Os
 .Sh NAME
@@ -35,6 +35,7 @@
 .Nd program to control CPUs
 .Sh SYNOPSIS
 .Nm cpuctl
+.Op Fl v
 .Ar command
 .Op Ar arguments
 .Sh DESCRIPTION
@@ -76,6 +77,12 @@ On success the
 .Cm identify
 command show different ucode versions before and after this command.
 .El
+.Pp
+Valid flags are:
+.Bl -tag -width indent
+.It Fl v
+Be more verbose.
+.El
 .Sh FILES
 .Bl -tag -width /dev/cpuctl -compact
 .It Pa /dev/cpuctl
@@ -91,7 +98,7 @@ where
 .Dv XX
 is the CPU family starting with 15 (hex).
 Get it from
-.Pa http://www.amd64.org/support/microcode.html
+.Lk http://www.amd64.org/microcode.html
 .El
 .Sh EXAMPLES
 Run

Index: src/usr.sbin/cpuctl/cpuctl.c
diff -u src/usr.sbin/cpuctl/cpuctl.c:1.20 src/usr.sbin/cpuctl/cpuctl.c:1.20.2.1
--- src/usr.sbin/cpuctl/cpuctl.c:1.20	Fri Jan 13 16:05:16 2012
+++ src/usr.sbin/cpuctl/cpuctl.c	Fri Jan 16 08:30:50 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuctl.c,v 1.20 2012/01/13 16:05:16 cegger Exp $	*/
+/*	$NetBSD: cpuctl.c,v 1.20.2.1 2015/01/16 08:30:50 snj Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009, 2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #ifndef lint
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: cpuctl.c,v 1.20 2012/01/13 16:05:16 cegger Exp $");
+__RCSID("$NetBSD: cpuctl.c,v 1.20.2.1 2015/01/16 08:30:50 snj Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -82,32 +82,44 @@ static struct cmdtab {
 };
 
 static int	fd;
+int		verbose;
 
 int
 main(int argc, char **argv)
 {
 	const struct cmdtab *ct;
+	int ch;
 
-	if (argc < 2)
+	while ((ch = getopt(argc, argv, "v")) != -1)
+		switch (ch) {
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+	if (argc < 1)
 		usage();
 
 	if ((fd = open(_PATH_CPUCTL, O_RDWR)) < 0)
 		err(EXIT_FAILURE, _PATH_CPUCTL);
 
 	for (ct = cpu_cmdtab; ct->label != NULL; ct++) {
-		if (strcmp(argv[1], ct->label) == 0) {
+		if (strcmp(argv[0], ct->label) == 0) {
 			if (!ct->argsoptional &&
-			    ((ct->takesargs == 0) ^ (argv[2] == NULL)))
+			    ((ct->takesargs == 0) ^ (argv[1] == NULL)))
 			{
 				usage();
 			}
-			(*ct->func)(argv + 2);
+			(*ct->func)(argv + 1);
 			break;
 		}
 	}
 
 	if (ct->label == NULL)
-		errx(EXIT_FAILURE, "unknown command ``%s''", argv[optind]);
+		errx(EXIT_FAILURE, "unknown command ``%s''", argv[0]);
 
 	close(fd);
 	exit(EXIT_SUCCESS);
@@ -221,7 +233,7 @@ cpu_identify(char **argv)
 	id = getcpuid(argv);
 	snprintf(name, sizeof(name), "cpu%u", id);
 
-	if (np != 0) {
+	if (np != 1) {
 		cpuset = cpuset_create();
 		if (cpuset == NULL)
 			err(EXIT_FAILURE, "cpuset_create");

Index: src/usr.sbin/cpuctl/cpuctl.h
diff -u src/usr.sbin/cpuctl/cpuctl.h:1.2 src/usr.sbin/cpuctl/cpuctl.h:1.2.10.1
--- src/usr.sbin/cpuctl/cpuctl.h:1.2	Tue Dec 16 22:44:51 2008
+++ src/usr.sbin/cpuctl/cpuctl.h	Fri Jan 16 08:30:50 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuctl.h,v 1.2 2008/12/16 22:44:51 christos Exp $	*/
+/*	$NetBSD: cpuctl.h,v 1.2.10.1 2015/01/16 08:30:50 snj Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,3 +34,5 @@ int	aprint_verbose_dev(const char *, con
 int	aprint_error_dev(const char *, const char *, ...);
 
 void	identifycpu(const char *);
+
+extern int verbose;

Index: src/usr.sbin/cpuctl/arch/i386-asm.S
diff -u src/usr.sbin/cpuctl/arch/i386-asm.S:1.1 src/usr.sbin/cpuctl/arch/i386-asm.S:1.1.24.1
--- src/usr.sbin/cpuctl/arch/i386-asm.S:1.1	Mon May  5 17:54:14 2008
+++ src/usr.sbin/cpuctl/arch/i386-asm.S	Fri Jan 16 08:30:50 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386-asm.S,v 1.1 2008/05/05 17:54:14 ad Exp $	*/
+/*	$NetBSD: i386-asm.S,v 1.1.24.1 2015/01/16 08:30:50 snj Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000, 2004, 2006, 2007 The NetBSD Foundation, Inc.
@@ -30,15 +30,6 @@
 #include <machine/cputypes.h>
 #include <machine/psl.h>
 
-	.data
-
-_C_LABEL(cpu):
-	.long	0
-	.globl	_C_LABEL(cpu)
-_C_LABEL(cpu_info_level):
-	.long	-1
-	.globl	_C_LABEL(cpu_info_level)
-
 	.text
 
 ENTRY(x86_cpuid2)
@@ -57,8 +48,12 @@ ENTRY(x86_cpuid2)
 	ret
 END(x86_cpuid2)
 
+ENTRY(x86_xgetbv)
+	xgetbv
+	ret
+END(x86_xgetbv)
+
 ENTRY(x86_identify)
-	pushl	%ebx
 	/* Try to toggle alignment check flag; does not exist on 386. */
 	pushfl
 	popl	%eax
@@ -91,11 +86,11 @@ isnx586:
 	 * Don't try cpuid, as Nx586s reportedly don't support the
 	 * PSL_ID bit.
 	 */
-	movl	$CPU_NX586,_C_LABEL(cpu)
-	jmp	2f
+	movl	$CPU_NX586,%eax
+	ret
 is386:
-	movl	$CPU_386,_C_LABEL(cpu)
-	jmp	2f
+	movl	$CPU_386,%eax
+	ret
 
 try486:	/* Try to toggle identification flag; does not exist on early 486s. */
 	pushfl
@@ -112,8 +107,13 @@ try486:	/* Try to toggle identification 
 	popfl
 
 	testl	%eax,%eax
-	jnz	try586
-is486:	movl	$CPU_486,_C_LABEL(cpu)
+	jz	is486
+
+	/* Later cpu, caller will use cpuid instruction */
+	movl	$-1,%eax
+	ret
+
+is486:
 	/*
 	 * Check Cyrix CPU
 	 * Cyrix CPUs do not change the undefined flags following
@@ -129,9 +129,11 @@ is486:	movl	$CPU_486,_C_LABEL(cpu)
 	divl	%ecx
 	jnc	trycyrix486
 	popfl
-	jmp 2f
+	movl	$CPU_486,%eax
+	ret
+
 trycyrix486:
-	movl	$CPU_6x86,_C_LABEL(cpu)	# set CPU type
+	popfl
 	/*
 	 * Check for Cyrix 486 CPU by seeing if the flags change during a
 	 * divide. This is documented in the Cx486SLC/e SMM Programmer's
@@ -139,6 +141,7 @@ trycyrix486:
 	 */
 	xorl	%edx,%edx
 	cmpl	%edx,%edx		# set flags to known state
+	pushl	%ebx
 	pushfl
 	popl	%ecx			# store flags in ecx
 	movl	$-1,%eax
@@ -146,15 +149,13 @@ trycyrix486:
 	divl	%ebx			# do a long division
 	pushfl
 	popl	%eax
+	popl	%ebx
 	xorl	%ecx,%eax		# are the flags different?
 	testl	$0x8d5,%eax		# only check C|PF|AF|Z|N|V
-	jne	2f			# yes; must be Cyrix 6x86 CPU
-	movl	$CPU_486DLC,_C_LABEL(cpu)# set CPU type
-	jmp	2f
-try586:	/* Use the `cpuid' instruction. */
-	xorl	%eax,%eax
-	cpuid
-	movl	%eax,_C_LABEL(cpu_info_level)
-2:
-	popl	%ebx
+	je	is486dlc		# yes => must be Cyrix 6x86 CPU
+	movl	$CPU_6x86,%eax
+	ret
+
+is486dlc:
+	movl	$CPU_486DLC,%eax
 	ret

Index: src/usr.sbin/cpuctl/arch/i386.c
diff -u src/usr.sbin/cpuctl/arch/i386.c:1.27.2.4 src/usr.sbin/cpuctl/arch/i386.c:1.27.2.5
--- src/usr.sbin/cpuctl/arch/i386.c:1.27.2.4	Thu Apr 19 20:04:37 2012
+++ src/usr.sbin/cpuctl/arch/i386.c	Fri Jan 16 08:30:50 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386.c,v 1.27.2.4 2012/04/19 20:04:37 riz Exp $	*/
+/*	$NetBSD: i386.c,v 1.27.2.5 2015/01/16 08:30:50 snj 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.27.2.4 2012/04/19 20:04:37 riz Exp $");
+__RCSID("$NetBSD: i386.c,v 1.27.2.5 2015/01/16 08:30:50 snj Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -81,25 +81,27 @@ __RCSID("$NetBSD: i386.c,v 1.27.2.4 2012
 #include <x86/cacheinfo.h>
 
 #include "../cpuctl.h"
+#include "cpuctl_i386.h"
 
 /* Size of buffer for printing humanized numbers */
 #define HUMAN_BUFSIZE sizeof("999KB")
 
-#define       x86_cpuid(a,b)  x86_cpuid2((a),0,(b))
-
-void	x86_cpuid2(uint32_t, uint32_t, uint32_t *);
-void	x86_identify(void);
-
 struct cpu_info {
 	const char	*ci_dev;
-	int32_t		ci_cpuid_level;
+	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_feat_val[5];	 /* X86 CPUID feature bits
+	uint32_t	ci_family;	 /* from ci_signature */
+	uint32_t	ci_model;	 /* from ci_signature */
+	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 */
@@ -110,6 +112,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 *);
 };
@@ -124,22 +130,17 @@ struct cpu_nocpuid_nameclass {
 	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;
 	int cpu_vendor;
 	const char *cpu_vendorname;
 	struct cpu_cpuid_family {
 		int cpu_class;
-		const char *cpu_models[CPU_MAXMODEL+2];
+		const char *cpu_models[256];
+		const char *cpu_model_default;
 		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];
 };
 
@@ -147,7 +148,9 @@ static const struct x86_cache_info intel
 
 /*
  * Map Brand ID from cpuid instruction to brand name.
- * Source: Intel Processor Identification and the CPUID Instruction, AP-485
+ * Source: Table 3-24, Mapping of Brand Indices; and Intel 64 and IA-32
+ * Processor Brand Strings, Chapter 3 in "Intel (R) 64 and IA-32
+ * Architectures Software Developer's Manual, Volume 2A".
  */
 static const char * const i386_intel_brand[] = {
 	"",		    /* Unsupported */
@@ -155,7 +158,7 @@ static const char * const i386_intel_bra
 	"Pentium III",      /* Intel (R) Pentium (R) III processor */
 	"Pentium III Xeon", /* Intel (R) Pentium (R) III Xeon (TM) processor */
 	"Pentium III",      /* Intel (R) Pentium (R) III processor */
-	"",		    /* Reserved */
+	"",		    /* 0x05: Reserved */
 	"Mobile Pentium III", /* Mobile Intel (R) Pentium (R) III processor-M */
 	"Mobile Celeron",   /* Mobile Intel (R) Celeron (R) processor */    
 	"Pentium 4",	    /* Intel (R) Pentium (R) 4 processor */
@@ -163,9 +166,17 @@ static const char * const i386_intel_bra
 	"Celeron",	    /* Intel (R) Celeron (TM) processor */
 	"Xeon",		    /* Intel (R) Xeon (TM) processor */
 	"Xeon MP",	    /* Intel (R) Xeon (TM) processor MP */
-	"",		    /* Reserved */
+	"",		    /* 0x0d: Reserved */
 	"Mobile Pentium 4", /* Mobile Intel (R) Pentium (R) 4 processor-M */
 	"Mobile Celeron",   /* Mobile Intel (R) Celeron (R) processor */
+	"",		    /* 0x10: Reserved */
+	"Mobile Genuine",   /* Moblie Genuine Intel (R) processor */
+	"Celeron M",        /* Intel (R) Celeron (R) M processor */
+	"Mobile Celeron",   /* Mobile Intel (R) Celeron (R) processor */
+	"Celeron",          /* Intel (R) Celeron (R) processor */
+	"Mobile Genuine",   /* Moblie Genuine Intel (R) processor */
+	"Pentium M",        /* Intel (R) Pentium (R) M processor */
+	"Mobile Celeron",   /* Mobile Intel (R) Celeron (R) processor */
 };
 
 /*
@@ -184,31 +195,38 @@ static char cpu_brand_string[49];
 static char amd_brand_name[48];
 static int use_pae, largepagesize;
 
-static void via_cpu_probe(struct cpu_info *);
-static void amd_family6_probe(struct cpu_info *);
-static void intel_family_new_probe(struct cpu_info *);
+/* Setup functions */
+static void	disable_tsc(struct cpu_info *);
+static void	amd_family5_setup(struct cpu_info *);
+static void	cyrix6x86_cpu_setup(struct cpu_info *);
+static void	winchip_cpu_setup(struct cpu_info *);
+/* Brand/Model name functions */
 static const char *intel_family6_name(struct cpu_info *);
 static const char *amd_amd64_name(struct cpu_info *);
-static void amd_family5_setup(struct cpu_info *);
-static void transmeta_cpu_info(struct cpu_info *);
-static const char *print_cache_config(struct cpu_info *, int, const char *,
-    const char *);
-static const char *print_tlb_config(struct cpu_info *, int, const char *,
-    const char *);
+/* Probe functions */
+static void	amd_family6_probe(struct cpu_info *);
+static void	powernow_probe(struct cpu_info *);
+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	x86_print_cacheinfo(struct cpu_info *);
+static void	tmx86_get_longrun_status(u_int *, u_int *, u_int *);
+static void	transmeta_cpu_info(struct cpu_info *);
+/* Common functions */
+static void	cpu_probe_base_features(struct cpu_info *, const char *);
+static void	cpu_probe_hv_features(struct cpu_info *, const char *);
+static void	cpu_probe_features(struct cpu_info *);
+static void	print_bits(const char *, const char *, const char *, uint32_t);
+static void	identifycpu_cpuids(struct cpu_info *);
 static const struct x86_cache_info *cache_info_lookup(
     const struct x86_cache_info *, uint8_t);
-static void cyrix6x86_cpu_setup(struct cpu_info *);
-static void winchip_cpu_setup(struct cpu_info *);
-static void amd_family5_setup(struct cpu_info *);
-static void powernow_probe(struct cpu_info *);
-
-/*
- * Info for CTL_HW
- */
-static char	cpu_model[120];
+static const char *print_cache_config(struct cpu_info *, int, const char *,
+    const char *);
+static const char *print_tlb_config(struct cpu_info *, int, const char *,
+    const char *);
+static void	x86_print_cache_and_tlb_info(struct cpu_info *);
 
 /*
  * Note: these are just the ones that may not have a cpuid instruction.
@@ -245,23 +263,13 @@ const char *modifiers[] = {
 	""
 };
 
-struct cpu_extend_nameclass intel_family6_ext_models[] = {
-	{ /* Extended models 1x */
-	  0x01, { NULL,			NULL,
-		  NULL,			NULL,
-		  NULL,			"EP80579 Integrated Processor",
-		  "Celeron (45nm)",	"Core 2 Extreme",
-		  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[] = {
 	{
+		/*
+		 * For Intel processors, check Chapter 35Model-specific
+		 * registers (MSRS), in "Intel (R) 64 and IA-32 Architectures
+		 * Software Developer's Manual, Volume 3C".
+		 */
 		"GenuineIntel",
 		CPUVENDOR_INTEL,
 		"Intel",
@@ -272,12 +280,11 @@ const struct cpu_cpuid_nameclass i386_cp
 				"486DX", "486DX", "486SX", "486DX2", "486SL",
 				"486SX2", 0, "486DX2 W/B Enhanced",
 				"486DX4", 0, 0, 0, 0, 0, 0, 0,
-				"486"		/* Default */
 			},
+			"486",		/* Default */
 			NULL,
 			NULL,
-			NULL,
-			NULL,
+			intel_cpu_cacheinfo,
 		},
 		/* Family 5 */
 		{
@@ -288,35 +295,81 @@ const struct cpu_cpuid_nameclass i386_cp
 				"Pentium/MMX", "Pentium", 0,
 				"Pentium (P54C)", "Pentium/MMX (Tillamook)",
 				0, 0, 0, 0, 0, 0, 0,
-				"Pentium"	/* Default */
 			},
+			"Pentium",	/* Default */
 			NULL,
 			NULL,
-			NULL,
-			NULL,
+			intel_cpu_cacheinfo,
 		},
 		/* Family 6 */
 		{
 			CPUCLASS_686,
 			{
-				"Pentium Pro (A-step)", "Pentium Pro", 0,
-				"Pentium II (Klamath)", "Pentium Pro",
-				"Pentium II/Celeron (Deschutes)",
-				"Celeron (Mendocino)",
-				"Pentium III (Katmai)",
-				"Pentium III (Coppermine)",
-				"Pentium M (Banias)", 
-				"Pentium III Xeon (Cascades)",
-				"Pentium III (Tualatin)", 0,
-				"Pentium M (Dothan)", 
-				"Pentium M (Yonah)",
-				"Core 2",
-				"Pentium Pro, II or III"	/* Default */
+				[0x00] = "Pentium Pro (A-step)",
+				[0x01] = "Pentium Pro",
+				[0x03] = "Pentium II (Klamath)",
+				[0x04] = "Pentium Pro",
+				[0x05] = "Pentium II/Celeron (Deschutes)",
+				[0x06] = "Celeron (Mendocino)",
+				[0x07] = "Pentium III (Katmai)",
+				[0x08] = "Pentium III (Coppermine)",
+				[0x09] = "Pentium M (Banias)", 
+				[0x0a] = "Pentium III Xeon (Cascades)",
+				[0x0b] = "Pentium III (Tualatin)",
+				[0x0d] = "Pentium M (Dothan)", 
+				[0x0e] = "Pentium Core Duo, Core solo",
+				[0x0f] = "Xeon 30xx, 32xx, 51xx, 53xx, 73xx, "
+					 "Core 2 Quad 6xxx, "
+					 "Core 2 Extreme 6xxx, "
+					 "Core 2 Duo 4xxx, 5xxx, 6xxx, 7xxx "
+					 "and Pentium DC",
+				[0x15] = "EP80579 Integrated Processor",
+				[0x16] = "Celeron (45nm)",
+				[0x17] = "Xeon 31xx, 33xx, 52xx, 54xx, "
+					 "Core 2 Quad 8xxx and 9xxx",
+				[0x1a] = "Core i7, Xeon 34xx, 35xx and 55xx "
+					 "(Nehalem)",
+				[0x1c] = "Atom Family",
+				[0x1d] = "XeonMP 74xx (Nehalem)",
+				[0x1e] = "Core i7 and i5",
+				[0x1f] = "Core i7 and i5",
+				[0x25] = "Xeon 36xx & 56xx, i7, i5 and i3",
+				[0x26] = "Atom Family",
+				[0x27] = "Atom Family",
+				[0x2a] = "Xeon E3-12xx, 2nd gen i7, i5, "
+					 "i3 2xxx",
+				[0x2c] = "Xeon 36xx & 56xx, i7, i5 and i3",
+				[0x2d] = "Xeon E5 Sandy Bridge family, "
+					 "Core i7-39xx Extreme",
+				[0x2e] = "Xeon 75xx & 65xx",
+				[0x2f] = "Xeon E7 family",
+				[0x35] = "Atom Family",
+				[0x36] = "Atom S1000",
+				[0x37] = "Atom E3000, Z3000",
+				[0x3a] = "Xeon E3-1200v2 and 3rd gen core, "
+					 "Ivy Bridge",
+				[0x3c] = "4th gen Core, Xeon E3-12xx v3 "
+					 "(Haswell)",
+				[0x3d] = "Core M-5xxx (Broadwell)",
+				[0x3e] = "Xeon E5/E7 v2 (Ivy Bridge-E), "
+					 "Core i7-49xx Extreme",
+				[0x3f] = "Xeon E5-2600/1600 v3 (Haswell-E), "
+					 "Core i7-59xx Extreme",
+				[0x45] = "4th gen Core, Xeon E3-12xx v3 "
+					 "(Haswell)",
+				[0x46] = "4th gen Core, Xeon E3-12xx v3 "
+					 "(Haswell)",
+				[0x4a] = "Future Atom E3000, Z3000",
+				[0x4d] = "Atom C2000",
+				[0x4e] = "Future Core",
+				[0x56] = "Future Xeon",
+				[0x5a] = "Future Atom E3000, Z3000",
+				[0x5d] = "Future Atom E3000, Z3000",
 			},
+			"Pentium Pro, II or III",	/* Default */
 			NULL,
 			intel_family_new_probe,
-			NULL,
-			&intel_family6_ext_models[0],
+			intel_cpu_cacheinfo,
 		},
 		/* Family > 6 */
 		{
@@ -324,12 +377,11 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Pentium 4"	/* Default */
 			},
+			"Pentium 4",	/* Default */
 			NULL,
 			intel_family_new_probe,
-			NULL,
-			NULL,
+			intel_cpu_cacheinfo,
 		} }
 	},
 	{
@@ -346,9 +398,8 @@ const struct cpu_cpuid_nameclass i386_cp
 				"Am486DX4 W/B or Am5x86 W/B 150", 0, 0,
 				0, 0, "Am5x86 W/T 133/160",
 				"Am5x86 W/B 133/160",
-				"Am486 or Am5x86"	/* Default */
 			},
-			NULL,
+			"Am486 or Am5x86",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -360,12 +411,11 @@ const struct cpu_cpuid_nameclass i386_cp
 				"K5", "K5", "K5", "K5", 0, 0, "K6",
 				"K6", "K6-2", "K6-III", "Geode LX", 0, 0,
 				"K6-2+/III+", 0, 0,
-				"K5 or K6"		/* Default */
 			},
+			"K5 or K6",		/* Default */
 			amd_family5_setup,
 			NULL,
 			amd_cpu_cacheinfo,
-			NULL,
 		},
 		/* Family 6 */
 		{
@@ -375,12 +425,11 @@ const struct cpu_cpuid_nameclass i386_cp
 				"Duron", "Athlon Model 4 (Thunderbird)",
 				0, "Athlon", "Duron", "Athlon", 0,
 				"Athlon", 0, 0, 0, 0, 0,
-				"K7 (Athlon)"	/* Default */
 			},
+			"K7 (Athlon)",	/* Default */
 			NULL,
 			amd_family6_probe,
 			amd_cpu_cacheinfo,
-			NULL,
 		},
 		/* Family > 6 */
 		{
@@ -388,12 +437,11 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Unknown K8 (Athlon)"	/* Default */
 			},
+			"Unknown K8 (Athlon)",	/* Default */
 			NULL,
 			amd_family6_probe,
 			amd_cpu_cacheinfo,
-			NULL,
 		} }
 	},
 	{
@@ -407,12 +455,11 @@ const struct cpu_cpuid_nameclass i386_cp
 				0, 0, 0,
 				"MediaGX",
 				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-				"486"		/* Default */
 			},
+			"486",		/* Default */
 			cyrix6x86_cpu_setup, /* XXX ?? */
 			NULL,
 			NULL,
-			NULL,
 		},
 		/* Family 5 */
 		{
@@ -421,12 +468,11 @@ const struct cpu_cpuid_nameclass i386_cp
 				0, 0, "6x86", 0,
 				"MMX-enhanced MediaGX (GXm)", /* or Geode? */
 				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-				"6x86"		/* Default */
 			},
+			"6x86",		/* Default */
 			cyrix6x86_cpu_setup,
 			NULL,
 			NULL,
-			NULL,
 		},
 		/* Family 6 */
 		{
@@ -434,12 +480,11 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				"6x86MX", 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"6x86MX"		/* Default */
 			},
+			"6x86MX",		/* Default */
 			cyrix6x86_cpu_setup,
 			NULL,
 			NULL,
-			NULL,
 		},
 		/* Family > 6 */
 		{
@@ -447,9 +492,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Unknown 6x86MX"		/* Default */
 			},
-			NULL,
+			"Unknown 6x86MX",		/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -465,9 +509,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"486 compatible"	/* Default */
 			},
-			NULL,
+			"486 compatible",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -479,12 +522,11 @@ const struct cpu_cpuid_nameclass i386_cp
 				0, 0, 0, 0,
 				"Geode GX1",
 				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-				"Geode"		/* Default */
 			},
+			"Geode",		/* Default */
 			cyrix6x86_cpu_setup,
 			NULL,
 			amd_cpu_cacheinfo,
-			NULL,
 		},
 		/* Family 6, not yet available from NSC */
 		{
@@ -492,9 +534,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Pentium Pro compatible" /* Default */
 			},
-			NULL,
+			"Pentium Pro compatible", /* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -505,9 +546,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Pentium Pro compatible"	/* Default */
 			},
-			NULL,
+			"Pentium Pro compatible",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -523,9 +563,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"486 compatible"	/* Default */
 			},
-			NULL,
+			"486 compatible",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -536,12 +575,11 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, "WinChip C6", 0, 0, 0,
 				"WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0,
-				"WinChip"		/* Default */
 			},
+			"WinChip",		/* Default */
 			winchip_cpu_setup,
 			NULL,
 			NULL,
-			NULL,
 		},
 		/* Family 6, VIA acquired IDT Centaur design subsidiary */
 		{
@@ -551,12 +589,11 @@ const struct cpu_cpuid_nameclass i386_cp
 				"C3 Samuel 2/Ezra", "C3 Ezra-T",
 				"C3 Nehemiah", "C7 Esther", 0, 0, "C7 Esther",
 				0, "VIA Nano",
-				"Unknown VIA/IDT"	/* Default */
 			},
+			"Unknown VIA/IDT",	/* Default */
 			NULL,
 			via_cpu_probe,
 			via_cpu_cacheinfo,
-			NULL,
 		},
 		/* Family > 6, not yet available from VIA */
 		{
@@ -564,9 +601,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Pentium Pro compatible"	/* Default */
 			},
-			NULL,
+			"Pentium Pro compatible",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -582,9 +618,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"486 compatible"	/* Default */
 			},
-			NULL,
+			"486 compatible",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -595,12 +630,11 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Crusoe"		/* Default */
 			},
+			"Crusoe",		/* Default */
 			NULL,
 			NULL,
 			transmeta_cpu_info,
-			NULL,
 		},
 		/* Family 6, not yet available from Transmeta */
 		{
@@ -608,9 +642,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Pentium Pro compatible"	/* Default */
 			},
-			NULL,
+			"Pentium Pro compatible",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -621,9 +654,8 @@ const struct cpu_cpuid_nameclass i386_cp
 			{
 				0, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0,
-				"Pentium Pro compatible"	/* Default */
 			},
-			NULL,
+			"Pentium Pro compatible",	/* Default */
 			NULL,
 			NULL,
 			NULL,
@@ -645,6 +677,29 @@ disable_tsc(struct cpu_info *ci)
 }
 
 static void
+amd_family5_setup(struct cpu_info *ci)
+{
+
+	switch (ci->ci_model) {
+	case 0:		/* AMD-K5 Model 0 */
+		/*
+		 * According to the AMD Processor Recognition App Note,
+		 * the AMD-K5 Model 0 uses the wrong bit to indicate
+		 * support for global PTEs, instead using bit 9 (APIC)
+		 * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
+		 */
+		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?
+		 */
+		break;
+	}
+}
+
+static void
 cyrix6x86_cpu_setup(struct cpu_info *ci)
 {
 
@@ -656,115 +711,23 @@ cyrix6x86_cpu_setup(struct cpu_info *ci)
 		disable_tsc(ci);
 }
 
-void
+static void
 winchip_cpu_setup(struct cpu_info *ci)
 {
-	switch (CPUID2MODEL(ci->ci_signature)) { /* model */
+	switch (ci->ci_model) {
 	case 4:	/* WinChip C6 */
 		disable_tsc(ci);
 	}
 }
 
 
-static void
-identifycpu_cpuids(struct cpu_info *ci)
-{
-	const char *cpuname = ci->ci_dev;
-	u_int lp_max = 1;	/* logical processors per package */
-	u_int smt_max;		/* smt per core */
-	u_int core_max = 1;	/* core per package */
-	u_int smt_bits, core_bits;
-	uint32_t descs[4];
-
-	aprint_verbose("%s: Initial APIC ID %u\n", cpuname, ci->ci_initapicid);
-	ci->ci_packageid = ci->ci_initapicid;
-	ci->ci_coreid = 0;
-	ci->ci_smtid = 0;
-	if (cpu_vendor != CPUVENDOR_INTEL) {
-		return;
-	}
-
-	/*
-	 * 253668.pdf 7.10.2
-	 */
-
-	if ((ci->ci_feat_val[0] & CPUID_HTT) != 0) {
-		x86_cpuid(1, descs);
-		lp_max = (descs[1] >> 16) & 0xff;
-	}
-	x86_cpuid(0, descs);
-	if (descs[0] >= 4) {
-		x86_cpuid2(4, 0, descs);
-		core_max = (descs[0] >> 26) + 1;
-	}
-	assert(lp_max >= core_max);
-	smt_max = lp_max / core_max;
-	smt_bits = ilog2(smt_max - 1) + 1;
-	core_bits = ilog2(core_max - 1) + 1;
-	if (smt_bits + core_bits) {
-		ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits);
-	}
-	aprint_verbose("%s: Cluster/Package ID %u\n", cpuname,
-	    ci->ci_packageid);
-	if (core_bits) {
-		u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1);
-
-		ci->ci_coreid =
-		    __SHIFTOUT(ci->ci_initapicid, core_mask);
-		aprint_verbose("%s: Core ID %u\n", cpuname, ci->ci_coreid);
-	}
-	if (smt_bits) {
-		u_int smt_mask = __BITS((int)0, (int)(smt_bits - 1));
-
-		ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask);
-		aprint_verbose("%s: SMT ID %u\n", cpuname, ci->ci_smtid);
-	}
-}
-
-static void
-via_cpu_probe(struct cpu_info *ci)
-{
-	u_int model = CPUID2MODEL(ci->ci_signature);
-	u_int stepping = CPUID2STEPPING(ci->ci_signature);
-	u_int descs[4];
-	u_int lfunc;
-
-	/*
-	 * Determine the largest extended function value.
-	 */
-	x86_cpuid(0x80000000, descs);
-	lfunc = descs[0];
-
-	/*
-	 * Determine the extended feature flags.
-	 */
-	if (lfunc >= 0x80000001) {
-		x86_cpuid(0x80000001, descs);
-		ci->ci_feat_val[2] |= descs[3];
-	}
-
-	if (model < 0x9 || (model == 0x9 && stepping < 3))
-		return;
-
-	/* Nehemiah or Esther */
-	x86_cpuid(0xc0000000, descs);
-	lfunc = descs[0];
-	if (lfunc < 0xc0000001)	/* no ACE, no RNG */
-		return;
-
-	x86_cpuid(0xc0000001, descs);
-	lfunc = descs[3];
-	ci->ci_feat_val[4] = lfunc;
-}
-
 static const char *
 intel_family6_name(struct cpu_info *ci)
 {
-	int model = CPUID2MODEL(ci->ci_signature);
 	const char *ret = NULL;
 	u_int l2cache = ci->ci_cinfo[CAI_L2CACHE].cai_totalsize;
 
-	if (model == 5) {
+	if (ci->ci_model == 5) {
 		switch (l2cache) {
 		case 0:
 		case 128 * 1024:
@@ -781,14 +744,14 @@ intel_family6_name(struct cpu_info *ci)
 			ret = "Pentium II Xeon";
 			break;
 		}
-	} else if (model == 6) {
+	} else if (ci->ci_model == 6) {
 		switch (l2cache) {
 		case 256 * 1024:
 		case 512 * 1024:
 			ret = "Mobile Pentium II";
 			break;
 		}
-	} else if (model == 7) {
+	} else if (ci->ci_model == 7) {
 		switch (l2cache) {
 		case 512 * 1024:
 			ret = "Pentium III";
@@ -798,7 +761,7 @@ intel_family6_name(struct cpu_info *ci)
 			ret = "Pentium III Xeon";
 			break;
 		}
-	} else if (model >= 8) {
+	} else if (ci->ci_model >= 8) {
 		if (ci->ci_brand_id && ci->ci_brand_id < 0x10) {
 			switch (ci->ci_brand_id) {
 			case 0x3:
@@ -835,291 +798,139 @@ intel_family6_name(struct cpu_info *ci)
  * "Revision Guide for AMD NPT Family 0Fh Processors"
  * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
  * and other miscellaneous reports.
+ *
+ * This is all rather pointless, these are cross 'brand' since the raw
+ * silicon is shared.
  */
 static const char *
 amd_amd64_name(struct cpu_info *ci)
 {
-	int extfamily, extmodel, model;
-	const char *ret = NULL;
+	static char family_str[32];
 
-	model = CPUID2MODEL(ci->ci_signature);
-	extfamily = CPUID2EXTFAMILY(ci->ci_signature);
-	extmodel  = CPUID2EXTMODEL(ci->ci_signature);
-
-	switch (extfamily) {
-	case 0x00:
-		switch (model) {
-		case 0x1:
-			switch (extmodel) {
-			case 0x2:	/* rev JH-E1/E6 */
-			case 0x4:	/* rev JH-F2 */
-				ret = "Dual-Core Opteron";
-				break;
-			}
-			break;
-		case 0x3:
-			switch (extmodel) {
-			case 0x2:	/* rev JH-E6 (Toledo) */
-				ret = "Dual-Core Opteron or Athlon 64 X2";
-				break;
-			case 0x4:	/* rev JH-F2 (Windsor) */
-				ret = "Athlon 64 FX or Athlon 64 X2";
-				break;
-			}
-			break;
-		case 0x4:
-			switch (extmodel) {
-			case 0x0:	/* rev SH-B0/C0/CG (ClawHammer) */
-			case 0x1:	/* rev SH-D0 */
-				ret = "Athlon 64";
-				break;
-			case 0x2:	/* rev SH-E5 (Lancaster?) */
-				ret = "Mobile Athlon 64 or Turion 64";
-				break;
-			}
-			break;
-		case 0x5:
-			switch (extmodel) {
-			case 0x0:	/* rev SH-B0/B3/C0/CG (SledgeHammer?) */
-				ret = "Opteron or Athlon 64 FX";
-				break;
-			case 0x1:	/* rev SH-D0 */
-			case 0x2:	/* rev SH-E4 */
-				ret = "Opteron";
-				break;
-			}
-			break;
-		case 0x7:
-			switch (extmodel) {
-			case 0x0:	/* rev SH-CG (ClawHammer) */
-			case 0x1:	/* rev SH-D0 */
-				ret = "Athlon 64";
-				break;
-			case 0x2:	/* rev DH-E4, SH-E4 */
-				ret = "Athlon 64 or Athlon 64 FX or Opteron";
-				break;
-			}
-			break;
-		case 0x8:
-			switch (extmodel) {
-			case 0x0:	/* rev CH-CG */
-			case 0x1:	/* rev CH-D0 */
-				ret = "Athlon 64 or Sempron";
-				break;
-			case 0x4:	/* rev BH-F2 */
-				ret = "Turion 64 X2";
-				break;
-			}
-			break;
-		case 0xb:
-			switch (extmodel) {
-			case 0x0:	/* rev CH-CG */
-			case 0x1:	/* rev CH-D0 */
-				ret = "Athlon 64";
-				break;
-			case 0x2:	/* rev BH-E4 (Manchester) */
-			case 0x4:	/* rev BH-F2 (Windsor) */
-				ret = "Athlon 64 X2";
-				break;
-			case 0x6:	/* rev BH-G1 (Brisbane) */
-				ret = "Athlon X2 or Athlon 64 X2";
-				break;
-			}
-			break;
-		case 0xc:
-			switch (extmodel) {
-			case 0x0:	/* rev DH-CG (Newcastle) */
-			case 0x1:	/* rev DH-D0 (Winchester) */
-			case 0x2:	/* rev DH-E3/E6 */
-				ret = "Athlon 64 or Sempron";
-				break;
-			}
-			break;
-		case 0xe:
-			switch (extmodel) {
-			case 0x0:	/* rev DH-CG (Newcastle?) */
-				ret = "Athlon 64 or Sempron";
-				break;
-			}
-			break;
-		case 0xf:
-			switch (extmodel) {
-			case 0x0:	/* rev DH-CG (Newcastle/Paris) */
-			case 0x1:	/* rev DH-D0 (Winchester/Victoria) */
-			case 0x2:	/* rev DH-E3/E6 (Venice/Palermo) */
-			case 0x4:	/* rev DH-F2 (Orleans/Manila) */
-			case 0x5:	/* rev DH-F2 (Orleans/Manila) */
-			case 0x6:	/* rev DH-G1 */
-				ret = "Athlon 64 or Sempron";
-				break;
-			}
-			break;
+	/* Only called if family >= 15 */
+
+	switch (ci->ci_family) {
+	case 15:
+		switch (ci->ci_model) {
+		case 0x21:	/* rev JH-E1/E6 */
+		case 0x41:	/* rev JH-F2 */
+			return "Dual-Core Opteron";
+		case 0x23:	/* rev JH-E6 (Toledo) */
+			return "Dual-Core Opteron or Athlon 64 X2";
+		case 0x43:	/* rev JH-F2 (Windsor) */
+			return "Athlon 64 FX or Athlon 64 X2";
+		case 0x24:	/* rev SH-E5 (Lancaster?) */
+			return "Mobile Athlon 64 or Turion 64";
+		case 0x05:	/* rev SH-B0/B3/C0/CG (SledgeHammer?) */
+			return "Opteron or Athlon 64 FX";
+		case 0x15:	/* rev SH-D0 */
+		case 0x25:	/* rev SH-E4 */
+			return "Opteron";
+		case 0x27:	/* rev DH-E4, SH-E4 */
+			return "Athlon 64 or Athlon 64 FX or Opteron";
+		case 0x48:	/* rev BH-F2 */
+			return "Turion 64 X2";
+		case 0x04:	/* rev SH-B0/C0/CG (ClawHammer) */
+		case 0x07:	/* rev SH-CG (ClawHammer) */
+		case 0x0b:	/* rev CH-CG */
+		case 0x14:	/* rev SH-D0 */
+		case 0x17:	/* rev SH-D0 */
+		case 0x1b:	/* rev CH-D0 */
+			return "Athlon 64";
+		case 0x2b:	/* rev BH-E4 (Manchester) */
+		case 0x4b:	/* rev BH-F2 (Windsor) */
+			return "Athlon 64 X2";
+		case 0x6b:	/* rev BH-G1 (Brisbane) */
+			return "Athlon X2 or Athlon 64 X2";
+		case 0x08:	/* rev CH-CG */
+		case 0x0c:	/* rev DH-CG (Newcastle) */
+		case 0x0e:	/* rev DH-CG (Newcastle?) */
+		case 0x0f:	/* rev DH-CG (Newcastle/Paris) */
+		case 0x18:	/* rev CH-D0 */
+		case 0x1c:	/* rev DH-D0 (Winchester) */
+		case 0x1f:	/* rev DH-D0 (Winchester/Victoria) */
+		case 0x2c:	/* rev DH-E3/E6 */
+		case 0x2f:	/* rev DH-E3/E6 (Venice/Palermo) */
+		case 0x4f:	/* rev DH-F2 (Orleans/Manila) */
+		case 0x5f:	/* rev DH-F2 (Orleans/Manila) */
+		case 0x6f:	/* rev DH-G1 */
+			return "Athlon 64 or Sempron";
 		default:
-			ret = "Unknown AMD64 CPU";
+			break;
 		}
-		break;
-	case 0x01:
-		ret = "Family 10h";
-		break;
-	case 0x02:
-		ret = "Family 11h";
-		break;
-	case 0x03:
-		ret = "Family 12h";
-		break;
-	case 0x05:
-		ret = "Family 14h";
-		break;
-	case 0x06:
-		ret = "Family 15h";
-		break;
+		return "Unknown AMD64 CPU";
+
+#if 0
+	case 16:
+		return "Family 10h";
+	case 17:
+		return "Family 11h";
+	case 18:
+		return "Family 12h";
+	case 19:
+		return "Family 14h";
+	case 20:
+		return "Family 15h";
+#endif
+
 	default:
-		ret = "Unknown AMD64 CPU";
 		break;
 	}
 
-	return ret;
+	snprintf(family_str, sizeof family_str, "Family %xh", ci->ci_family);
+	return family_str;
 }
 
 static void
-cpu_probe_base_features(struct cpu_info *ci)
+intel_family_new_probe(struct cpu_info *ci)
 {
-	const struct x86_cache_info *cai;
-	u_int descs[4];
-	int iterations, i, j;
-	uint8_t desc;
-	uint32_t miscbytes;
-	uint32_t brand[12];
-
-	if (ci->ci_cpuid_level < 0)
-		return;
+	uint32_t descs[4];
 
-	x86_cpuid(0, descs);
-	ci->ci_cpuid_level = descs[0];
-	ci->ci_vendor[0] = descs[1];
-	ci->ci_vendor[2] = descs[2];
-	ci->ci_vendor[1] = descs[3];
-	ci->ci_vendor[3] = 0;
+	x86_cpuid(0x80000000, descs);
 
-	x86_cpuid(0x80000000, brand);
-	if (brand[0] >= 0x80000004) {
-		x86_cpuid(0x80000002, brand);
-		x86_cpuid(0x80000003, brand + 4);
-		x86_cpuid(0x80000004, brand + 8);
-		for (i = 0; i < 48; i++)
-			if (((char *) brand)[i] != ' ')
-				break;
-		memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i);
+	/*
+	 * Determine extended feature flags.
+	 */
+	if (descs[0] >= 0x80000001) {
+		x86_cpuid(0x80000001, descs);
+		ci->ci_feat_val[2] |= descs[3];
+		ci->ci_feat_val[3] |= descs[2];
 	}
+}
 
-	if (ci->ci_cpuid_level < 1)
-		return;
-
-	x86_cpuid(1, descs);
-	ci->ci_signature = descs[0];
-	miscbytes = descs[1];
-	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;
-	ci->ci_initapicid = (miscbytes >> 24) & 0xff;
-	if (ci->ci_cpuid_level < 2)
-		return;
+static void
+via_cpu_probe(struct cpu_info *ci)
+{
+	u_int stepping = CPUID2STEPPING(ci->ci_signature);
+	u_int descs[4];
+	u_int lfunc;
 
 	/*
-	 * Parse the cache info from `cpuid', if we have it.
-	 * XXX This is kinda ugly, but hey, so is the architecture...
+	 * Determine the largest extended function value.
 	 */
-
-	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;
+	x86_cpuid(0x80000000, descs);
+	lfunc = descs[0];
 
 	/*
-	 * If the processor serial number misfeature is present and supported,
-	 * extract it here.
+	 * Determine the extended feature flags.
 	 */
-	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];
-		ci->ci_cpu_serial[1] = descs[3];
-	}
-}
-
-static void
-cpu_probe_features(struct cpu_info *ci)
-{
-	const struct cpu_cpuid_nameclass *cpup = NULL;
-	int i, xmax, family;
-
-	cpu_probe_base_features(ci);
-
-	if (ci->ci_cpuid_level < 1)
-		return;
-
-	xmax = __arraycount(i386_cpuid_cpus);
-	for (i = 0; i < xmax; i++) {
-		if (!strncmp((char *)ci->ci_vendor,
-		    i386_cpuid_cpus[i].cpu_id, 12)) {
-			cpup = &i386_cpuid_cpus[i];
-			break;
-		}
+	if (lfunc >= 0x80000001) {
+		x86_cpuid(0x80000001, descs);
+		ci->ci_feat_val[2] |= descs[3];
 	}
 
-	if (cpup == NULL)
+	if (ci->ci_model < 0x9 || (ci->ci_model == 0x9 && stepping < 3))
 		return;
 
-	family = (ci->ci_signature >> 8) & 0xf;
-
-	if (family > CPU_MAXFAMILY) {
-		family = CPU_MAXFAMILY;
-	}
-	i = family - CPU_MINFAMILY;
-
-	if (cpup->cpu_family[i].cpu_probe == NULL)
+	/* Nehemiah or Esther */
+	x86_cpuid(0xc0000000, descs);
+	lfunc = descs[0];
+	if (lfunc < 0xc0000001)	/* no ACE, no RNG */
 		return;
 
-	(*cpup->cpu_family[i].cpu_probe)(ci);
-}
-
-static void
-intel_family_new_probe(struct cpu_info *ci)
-{
-	uint32_t descs[4];
-
-	x86_cpuid(0x80000000, descs);
-
-	/*
-	 * Determine extended feature flags.
-	 */
-	if (descs[0] >= 0x80000001) {
-		x86_cpuid(0x80000001, descs);
-		ci->ci_feat_val[2] |= descs[3];
-		ci->ci_feat_val[3] |= descs[2];
-	}
+	x86_cpuid(0xc0000001, descs);
+	lfunc = descs[3];
+	ci->ci_feat_val[4] = lfunc;
 }
 
 static void
@@ -1152,774 +963,1117 @@ amd_family6_probe(struct cpu_info *ci)
 }
 
 static void
-amd_family5_setup(struct cpu_info *ci)
-{
-
-	switch (CPUID2MODEL(ci->ci_signature)) {
-	case 0:		/* AMD-K5 Model 0 */
-		/*
-		 * According to the AMD Processor Recognition App Note,
-		 * the AMD-K5 Model 0 uses the wrong bit to indicate
-		 * support for global PTEs, instead using bit 9 (APIC)
-		 * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
-		 */
-		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?
-		 */
-		break;
-	}
-}
-
-static void
-tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage)
+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;
 
-	x86_cpuid(0x80860007, descs);
-	*frequency = descs[0];
-	*voltage = descs[1];
-	*percentage = descs[2];
-}
-
-static void
-transmeta_cpu_info(struct cpu_info *ci)
-{
-	u_int descs[4], nreg;
-	u_int frequency, voltage, percentage;
+	/* Return if the cpu is old pre-cpuid instruction cpu */
+	if (ci->ci_cpu_type >= 0)
+		return;
 
-	x86_cpuid(0x80860000, descs);
-	nreg = descs[0];
-	if (nreg >= 0x80860001) {
-		x86_cpuid(0x80860001, descs);
-		aprint_verbose_dev(ci->ci_dev, "Processor revision %u.%u.%u.%u\n",
-		    (descs[1] >> 24) & 0xff,
-		    (descs[1] >> 16) & 0xff,
-		    (descs[1] >> 8) & 0xff,
-		    descs[1] & 0xff);
-	}
-	if (nreg >= 0x80860002) {
-		x86_cpuid(0x80860002, descs);
-		aprint_verbose_dev(ci->ci_dev, "Code Morphing Software Rev: %u.%u.%u-%u-%u\n",
-		    (descs[1] >> 24) & 0xff,
-		    (descs[1] >> 16) & 0xff,
-		    (descs[1] >> 8) & 0xff,
-		    descs[1] & 0xff,
-		    descs[2]);
-	}
-	if (nreg >= 0x80860006) {
-		union {
-			char text[65];
-			u_int descs[4][4];
-		} info;
-		int i;
+	if (ci->ci_cpuid_level < 2)
+		return;
 
-		for (i=0; i<4; i++) {
-			x86_cpuid(0x80860003 + i, info.descs[i]);
+	/*
+	 * 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;
+				else if ((verbose != 0) && (desc != 0xff))
+					printf("Unknown cacheinfo desc %02x\n",
+					    desc);
+			}
 		}
-		info.text[64] = '\0';
-		aprint_verbose_dev(ci->ci_dev, "%s\n", info.text);
+		x86_cpuid(2, descs);
 	}
 
-	if (nreg >= 0x80860007) {
-		tmx86_get_longrun_status(&frequency,
-		    &voltage, &percentage);
-		aprint_verbose_dev(ci->ci_dev, "LongRun <%dMHz %dmV %d%%>\n",
-		    frequency, voltage, percentage);
+	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;
 	}
 }
 
-void
-identifycpu(const char *cpuname)
+static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = 
+    AMD_L2CACHE_INFO;
+
+static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] = 
+    AMD_L3CACHE_INFO;
+
+static void
+amd_cpu_cacheinfo(struct cpu_info *ci)
 {
-	const char *name = "", *modifier, *vendorname, *brand = "";
-	int class = CPUCLASS_386, i, xmax;
-	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];
-	struct cpu_info *ci, cistore;
-	extern int cpu;
-	extern int cpu_info_level;
-	size_t sz;
-	char buf[512];
-	char *bp;
+	const struct x86_cache_info *cp;
+	struct x86_cache_info *cai;
+	u_int descs[4];
+	u_int lfunc;
 
-	ci = &cistore;
-	memset(ci, 0, sizeof(*ci));
-	ci->ci_dev = cpuname;
+	/*
+	 * K5 model 0 has none of this info.
+	 */
+	if (ci->ci_family == 5 && ci->ci_model == 0)
+		return;
 
-	x86_identify();
-	ci->ci_cpuid_level = cpu_info_level;
-	cpu_probe_features(ci);
+	/*
+	 * Determine the largest extended function value.
+	 */
+	x86_cpuid(0x80000000, descs);
+	lfunc = descs[0];
 
-	if (ci->ci_cpuid_level == -1) {
-		if ((size_t)cpu >= __arraycount(i386_nocpuid_cpus))
-			errx(1, "unknown cpu type %d", cpu);
-		name = i386_nocpuid_cpus[cpu].cpu_name;
-		cpu_vendor = i386_nocpuid_cpus[cpu].cpu_vendor;
-		vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname;
-		class = i386_nocpuid_cpus[cpu].cpu_class;
-		ci->ci_info = i386_nocpuid_cpus[cpu].cpu_info;
-		modifier = "";
-	} else {
-		xmax = __arraycount(i386_cpuid_cpus);
-		modif = (ci->ci_signature >> 12) & 0x3;
-		family = CPUID2FAMILY(ci->ci_signature);
-		if (family < CPU_MINFAMILY)
-			errx(1, "identifycpu: strange family value");
-		model = CPUID2MODEL(ci->ci_signature);
-		ext_model = CPUID2EXTMODEL(ci->ci_signature);
+	/*
+	 * Determine L1 cache/TLB info.
+	 */
+	if (lfunc < 0x80000005) {
+		/* No L1 cache info available. */
+		return;
+	}
 
-		for (i = 0; i < xmax; i++) {
-			if (!strncmp((char *)ci->ci_vendor,
-			    i386_cpuid_cpus[i].cpu_id, 12)) {
-				cpup = &i386_cpuid_cpus[i];
-				break;
-			}
-		}
+	x86_cpuid(0x80000005, descs);
 
-		if (cpup == NULL) {
-			cpu_vendor = CPUVENDOR_UNKNOWN;
-			if (ci->ci_vendor[0] != '\0')
-				vendorname = (char *)&ci->ci_vendor[0];
-			else
-				vendorname = "Unknown";
-			if (family >= CPU_MAXFAMILY)
-				family = CPU_MINFAMILY;
-			class = family - 3;
-			modifier = "";
-			name = "";
-			ci->ci_info = NULL;
-		} else {
-			cpu_vendor = cpup->cpu_vendor;
-			vendorname = cpup->cpu_vendorname;
-			modifier = modifiers[modif];
-			if (family > CPU_MAXFAMILY) {
-				family = CPU_MAXFAMILY;
-				model = CPU_DEFMODEL;
-			} else if (model > CPU_MAXMODEL) {
-				model = CPU_DEFMODEL;
-				ext_model = 0;
-			}
-			cpufam = &cpup->cpu_family[family - CPU_MINFAMILY];
-			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;
+	/*
+	 * K6-III and higher have large page TLBs.
+	 */
+	if ((ci->ci_family == 5 && ci->ci_model >= 9) || ci->ci_family >= 6) {
+		cai = &ci->ci_cinfo[CAI_ITLB2];
+		cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
+		cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
+		cai->cai_linesize = largepagesize;
 
-			if (cpu_vendor == CPUVENDOR_INTEL) {
-				if (family == 6 && model >= 5) {
-					const char *tmp;
-					tmp = intel_family6_name(ci);
-					if (tmp != NULL)
-						name = tmp;
-				}
-				if (family == CPU_MAXFAMILY &&
-				    ci->ci_brand_id <
-				    __arraycount(i386_intel_brand) &&
-				    i386_intel_brand[ci->ci_brand_id])
-					name =
-					     i386_intel_brand[ci->ci_brand_id];
-			}
+		cai = &ci->ci_cinfo[CAI_DTLB2];
+		cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
+		cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
+		cai->cai_linesize = largepagesize;
+	}
+
+	cai = &ci->ci_cinfo[CAI_ITLB];
+	cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
+	cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
+	cai->cai_linesize = (4 * 1024);
+
+	cai = &ci->ci_cinfo[CAI_DTLB];
+	cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
+	cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
+	cai->cai_linesize = (4 * 1024);
+
+	cai = &ci->ci_cinfo[CAI_DCACHE];
+	cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
+	cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
+	cai->cai_linesize = AMD_L1_ECX_DC_LS(descs[2]);
+
+	cai = &ci->ci_cinfo[CAI_ICACHE];
+	cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
+	cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
+	cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
+
+	/*
+	 * Determine L2 cache/TLB info.
+	 */
+	if (lfunc < 0x80000006) {
+		/* No L2 cache info available. */
+		return;
+	}
+
+	x86_cpuid(0x80000006, descs);
+
+	cai = &ci->ci_cinfo[CAI_L2_ITLB];
+	cai->cai_totalsize = AMD_L2_EBX_IUTLB_ENTRIES(descs[1]);
+	cai->cai_associativity = AMD_L2_EBX_IUTLB_ASSOC(descs[1]);
+	cai->cai_linesize = (4 * 1024);
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	cai = &ci->ci_cinfo[CAI_L2_ITLB2];
+	cai->cai_totalsize = AMD_L2_EAX_IUTLB_ENTRIES(descs[0]);
+	cai->cai_associativity = AMD_L2_EAX_IUTLB_ASSOC(descs[0]);
+	cai->cai_linesize = largepagesize;
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	cai = &ci->ci_cinfo[CAI_L2_DTLB];
+	cai->cai_totalsize = AMD_L2_EBX_DTLB_ENTRIES(descs[1]);
+	cai->cai_associativity = AMD_L2_EBX_DTLB_ASSOC(descs[1]);
+	cai->cai_linesize = (4 * 1024);
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	cai = &ci->ci_cinfo[CAI_L2_DTLB2];
+	cai->cai_totalsize = AMD_L2_EAX_DTLB_ENTRIES(descs[0]);
+	cai->cai_associativity = AMD_L2_EAX_DTLB_ASSOC(descs[0]);
+	cai->cai_linesize = largepagesize;
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	cai = &ci->ci_cinfo[CAI_L2CACHE];
+	cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
+	cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
+	cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
+
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	/*
+	 * Determine L3 cache info on AMD Family 10h and newer processors
+	 */
+	if (ci->ci_family >= 0x10) {
+		cai = &ci->ci_cinfo[CAI_L3CACHE];
+		cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]);
+		cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]);
+		cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]);
+
+		cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info,
+		    cai->cai_associativity);
+		if (cp != NULL)
+			cai->cai_associativity = cp->cai_associativity;
+		else
+			cai->cai_associativity = 0;	/* XXX Unkn/Rsvd */
+	}
+
+	/*
+	 * Determine 1GB TLB info.
+	 */
+	if (lfunc < 0x80000019) {
+		/* No 1GB TLB info available. */
+		return;
+	}
+
+	x86_cpuid(0x80000019, descs);
+
+	cai = &ci->ci_cinfo[CAI_L1_1GBITLB];
+	cai->cai_totalsize = AMD_L1_1GB_EAX_IUTLB_ENTRIES(descs[0]);
+	cai->cai_associativity = AMD_L1_1GB_EAX_IUTLB_ASSOC(descs[0]);
+	cai->cai_linesize = (1024 * 1024 * 1024);
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	cai = &ci->ci_cinfo[CAI_L1_1GBDTLB];
+	cai->cai_totalsize = AMD_L1_1GB_EAX_DTLB_ENTRIES(descs[0]);
+	cai->cai_associativity = AMD_L1_1GB_EAX_DTLB_ASSOC(descs[0]);
+	cai->cai_linesize = (1024 * 1024 * 1024);
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	cai = &ci->ci_cinfo[CAI_L2_1GBITLB];
+	cai->cai_totalsize = AMD_L2_1GB_EBX_IUTLB_ENTRIES(descs[1]);
+	cai->cai_associativity = AMD_L2_1GB_EBX_IUTLB_ASSOC(descs[1]);
+	cai->cai_linesize = (1024 * 1024 * 1024);
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+
+	cai = &ci->ci_cinfo[CAI_L2_1GBDTLB];
+	cai->cai_totalsize = AMD_L2_1GB_EBX_DUTLB_ENTRIES(descs[1]);
+	cai->cai_associativity = AMD_L2_1GB_EBX_DUTLB_ASSOC(descs[1]);
+	cai->cai_linesize = (1024 * 1024 * 1024);
+	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+	    cai->cai_associativity);
+	if (cp != NULL)
+		cai->cai_associativity = cp->cai_associativity;
+	else
+		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+}
+
+static void
+via_cpu_cacheinfo(struct cpu_info *ci)
+{
+	struct x86_cache_info *cai;
+	int stepping;
+	u_int descs[4];
+	u_int lfunc;
+
+	stepping = CPUID2STEPPING(ci->ci_signature);
+
+	/*
+	 * Determine the largest extended function value.
+	 */
+	x86_cpuid(0x80000000, descs);
+	lfunc = descs[0];
+
+	/*
+	 * Determine L1 cache/TLB info.
+	 */
+	if (lfunc < 0x80000005) {
+		/* No L1 cache info available. */
+		return;
+	}
+
+	x86_cpuid(0x80000005, descs);
+
+	cai = &ci->ci_cinfo[CAI_ITLB];
+	cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]);
+	cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]);
+	cai->cai_linesize = (4 * 1024);
+
+	cai = &ci->ci_cinfo[CAI_DTLB];
+	cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]);
+	cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]);
+	cai->cai_linesize = (4 * 1024);
+
+	cai = &ci->ci_cinfo[CAI_DCACHE];
+	cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]);
+	cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]);
+	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]);
+	if (ci->ci_model == 9 && stepping == 8) {
+		/* Erratum: stepping 8 reports 4 when it should be 2 */
+		cai->cai_associativity = 2;
+	}
+
+	cai = &ci->ci_cinfo[CAI_ICACHE];
+	cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]);
+	cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]);
+	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]);
+	if (ci->ci_model == 9 && stepping == 8) {
+		/* Erratum: stepping 8 reports 4 when it should be 2 */
+		cai->cai_associativity = 2;
+	}
+
+	/*
+	 * Determine L2 cache/TLB info.
+	 */
+	if (lfunc < 0x80000006) {
+		/* No L2 cache info available. */
+		return;
+	}
+
+	x86_cpuid(0x80000006, descs);
+
+	cai = &ci->ci_cinfo[CAI_L2CACHE];
+	if (ci->ci_model >= 9) {
+		cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]);
+		cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]);
+		cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]);
+	} else {
+		cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]);
+		cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]);
+		cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]);
+	}
+}
+
+static void
+tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage)
+{
+	u_int descs[4];
+
+	x86_cpuid(0x80860007, descs);
+	*frequency = descs[0];
+	*voltage = descs[1];
+	*percentage = descs[2];
+}
+
+static void
+transmeta_cpu_info(struct cpu_info *ci)
+{
+	u_int descs[4], nreg;
+	u_int frequency, voltage, percentage;
+
+	x86_cpuid(0x80860000, descs);
+	nreg = descs[0];
+	if (nreg >= 0x80860001) {
+		x86_cpuid(0x80860001, descs);
+		aprint_verbose_dev(ci->ci_dev, "Processor revision %u.%u.%u.%u\n",
+		    (descs[1] >> 24) & 0xff,
+		    (descs[1] >> 16) & 0xff,
+		    (descs[1] >> 8) & 0xff,
+		    descs[1] & 0xff);
+	}
+	if (nreg >= 0x80860002) {
+		x86_cpuid(0x80860002, descs);
+		aprint_verbose_dev(ci->ci_dev, "Code Morphing Software Rev: %u.%u.%u-%u-%u\n",
+		    (descs[1] >> 24) & 0xff,
+		    (descs[1] >> 16) & 0xff,
+		    (descs[1] >> 8) & 0xff,
+		    descs[1] & 0xff,
+		    descs[2]);
+	}
+	if (nreg >= 0x80860006) {
+		union {
+			char text[65];
+			u_int descs[4][4];
+		} info;
+		int i;
 
-			if (cpu_vendor == CPUVENDOR_AMD) {
-				if (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;
-				}
-				if (CPUID2FAMILY(ci->ci_signature) == 0xf) {
-					/*
-					 * Identify AMD64 CPU names.
-					 * Note family value is clipped by
-					 * CPU_MAXFAMILY.
-					 */
-					const char *tmp;
-					tmp = amd_amd64_name(ci);
-					if (tmp != NULL)
-						name = tmp;
-				}
-			}
-			
-			if (cpu_vendor == CPUVENDOR_IDT && family >= 6)
-				vendorname = "VIA";
+		for (i=0; i<4; i++) {
+			x86_cpuid(0x80860003 + i, info.descs[i]);
 		}
+		info.text[64] = '\0';
+		aprint_verbose_dev(ci->ci_dev, "%s\n", info.text);
 	}
 
-	ci->ci_cpu_class = class;
-
-	sz = sizeof(ci->ci_tsc_freq);
-	(void)sysctlbyname("machdep.tsc_freq", &ci->ci_tsc_freq, &sz, NULL, 0);
-	sz = sizeof(use_pae);
-	(void)sysctlbyname("machdep.pae", &use_pae, &sz, NULL, 0);
-	largepagesize = (use_pae ? 2 * 1024 * 1024 : 4 * 1024 * 1024);
+	if (nreg >= 0x80860007) {
+		tmx86_get_longrun_status(&frequency,
+		    &voltage, &percentage);
+		aprint_verbose_dev(ci->ci_dev, "LongRun <%dMHz %dmV %d%%>\n",
+		    frequency, voltage, percentage);
+	}
+}
 
-	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);
+static void
+cpu_probe_base_features(struct cpu_info *ci, const char *cpuname)
+{
+	u_int descs[4];
+	int i;
+	uint32_t brand[12];
 
-	if (ci->ci_tsc_freq != 0)
-		aprint_normal(", %ju.%02ju MHz",
-		    ((uintmax_t)ci->ci_tsc_freq + 4999) / 1000000,
-		    (((uintmax_t)ci->ci_tsc_freq + 4999) / 10000) % 100);
-	if (ci->ci_signature != 0)
-		aprint_normal(", id 0x%x", ci->ci_signature);
-	aprint_normal("\n");
+	memset(ci, 0, sizeof(*ci));
+	ci->ci_dev = cpuname;
 
-	if (ci->ci_info)
-		(*ci->ci_info)(ci);
+	ci->ci_cpu_type = x86_identify();
+	if (ci->ci_cpu_type >= 0) {
+		/* Old pre-cpuid instruction cpu */
+		ci->ci_cpuid_level = -1;
+		return;
+	}
 
 	/*
-	 * display CPU feature flags
+	 * This CPU supports cpuid instruction, so we can call x86_cpuid()
+	 * function.
 	 */
 
-#define	MAX_FEATURE_LEN	60	/* XXX Need to find a better way to set this */
-
-	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;
-	}
-	
-	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);
+	/*
+	 * Fn0000_0000:
+	 * - Save cpuid max level.
+	 * - Save vendor string.
+	 */
+	x86_cpuid(0, descs);
+	ci->ci_cpuid_level = descs[0];
+	/* Save vendor string */
+	ci->ci_vendor[0] = descs[1];
+	ci->ci_vendor[2] = descs[2];
+	ci->ci_vendor[1] = descs[3];
+	ci->ci_vendor[3] = 0;
 
-	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,
-		    ci->ci_cpu_serial[1] / 65536, ci->ci_cpu_serial[1] % 65536,
-		    ci->ci_cpu_serial[2] / 65536, ci->ci_cpu_serial[2] % 65536);
+	/*
+	 * 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;
 	}
 
-	if (ci->ci_cpu_class == CPUCLASS_386) {
-		errx(1, "NetBSD requires an 80486 or later processor");
+	/*
+	 * Fn8000_000[2-4]:
+	 * - Save brand string.
+	 */
+	if (ci->ci_cpuid_extlevel >= 0x80000004) {
+		x86_cpuid(0x80000002, brand);
+		x86_cpuid(0x80000003, brand + 4);
+		x86_cpuid(0x80000004, brand + 8);
+		for (i = 0; i < 48; i++)
+			if (((char *) brand)[i] != ' ')
+				break;
+		memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i);
 	}
 
-	if (cpu == CPU_486DLC) {
-#ifndef CYRIX_CACHE_WORKS
-		aprint_error("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
-#else
-#ifndef CYRIX_CACHE_REALLY_WORKS
-		aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
-#else
-		aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
-#endif
-#endif
-	}
+	if (ci->ci_cpuid_level < 1)
+		return;
 
 	/*
-	 * Everything past this point requires a Pentium or later.
+	 * 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)
 	 */
-	if (ci->ci_cpuid_level < 0)
-		return;
-
-	identifycpu_cpuids(ci);
+	x86_cpuid(1, descs);
+	ci->ci_signature = descs[0];
 
-#ifdef INTEL_CORETEMP
-	if (cpu_vendor == CPUVENDOR_INTEL && ci->ci_cpuid_level >= 0x06)
-		coretemp_register(ci);
-#endif
+	/* Extract full family/model values */
+	ci->ci_family = CPUID2FAMILY(ci->ci_signature);
+	ci->ci_model = CPUID2MODEL(ci->ci_signature);
+	if (ci->ci_family == 15)
+		ci->ci_family += CPUID2EXTFAMILY(ci->ci_signature);
+	if (ci->ci_family == 6 || ci->ci_family == 15)
+		ci->ci_model += CPUID2EXTMODEL(ci->ci_signature) << 4;
 
-	if (cpu_vendor == CPUVENDOR_AMD) {
-		uint32_t data[4];
+	/* Brand is low order 8 bits of ebx */
+	ci->ci_brand_id = descs[1] & 0xff;
+	/* Initial local APIC ID */
+	ci->ci_initapicid = (descs[1] >> 24) & 0xff;
 
-		x86_cpuid(0x80000000, data);
-		if (data[0] >= 0x80000007)
-			powernow_probe(ci);
+	ci->ci_feat_val[1] = descs[2];
+	ci->ci_feat_val[0] = descs[3];
 
-		if ((data[0] >= 0x8000000a)
-		   && (ci->ci_feat_val[3] & CPUID_SVM) != 0) {
+	if (ci->ci_cpuid_level < 3)
+		return;
 
-			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;
-			}
-		}
+	/*
+	 * If the processor serial number misfeature is present and supported,
+	 * extract it here.
+	 */
+	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];
+		ci->ci_cpu_serial[1] = descs[3];
 	}
 
-#ifdef INTEL_ONDEMAND_CLOCKMOD
-	clockmod_init();
-#endif
+	if (ci->ci_cpuid_level < 0xd)
+		return;
 
-	aprint_normal_dev(ci->ci_dev, "family %02x model %02x "
-	    "extfamily %02x extmodel %02x stepping %02x\n",
-	    CPUID2FAMILY(ci->ci_signature), CPUID2MODEL(ci->ci_signature),
-	    CPUID2EXTFAMILY(ci->ci_signature), CPUID2EXTMODEL(ci->ci_signature),
-	    CPUID2STEPPING(ci->ci_signature));
+	/* Get support XCR0 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 const char *
-print_cache_config(struct cpu_info *ci, int cache_tag, const char *name,
-    const char *sep)
+static void
+cpu_probe_hv_features(struct cpu_info *ci, const char *cpuname)
 {
-	struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
-	char human_num[HUMAN_BUFSIZE];
-
-	if (cai->cai_totalsize == 0)
-		return sep;
+	uint32_t descs[4];
+	char hv_sig[13];
+	char *p;
+	const char *hv_name;
+	int i;
 
-	if (sep == NULL)
-		aprint_verbose_dev(ci->ci_dev, "");
-	else
-		aprint_verbose("%s", sep);
-	if (name != NULL)
-		aprint_verbose("%s ", name);
+	/*
+	 * [RFC] CPUID usage for interaction between Hypervisors and Linux.
+	 * http://lkml.org/lkml/2008/10/1/246
+	 *
+	 * KB1009458: Mechanisms to determine if software is running in
+	 * a VMware virtual machine
+	 * http://kb.vmware.com/kb/1009458
+	 */
+	if ((ci->ci_feat_val[1] & CPUID2_RAZ) != 0) {
+		x86_cpuid(0x40000000, descs);
+		for (i = 1, p = hv_sig; i < 4; i++, p += sizeof(descs) / 4)
+			memcpy(p, &descs[i], sizeof(descs[i]));
+		*p = '\0';
+		/*
+		 * HV vendor	ID string
+		 * ------------+--------------
+		 * KVM		"KVMKVMKVM"
+		 * Microsoft	"Microsoft Hv"
+		 * VMware	"VMwareVMware"
+		 * Xen		"XenVMMXenVMM"
+		 */
+		if (strncmp(hv_sig, "KVMKVMKVM", 9) == 0)
+			hv_name = "KVM";
+		else if (strncmp(hv_sig, "Microsoft Hv", 12) == 0)
+			hv_name = "Hyper-V";
+		else if (strncmp(hv_sig, "VMwareVMware", 12) == 0)
+			hv_name = "VMware";
+		else if (strncmp(hv_sig, "XenVMMXenVMM", 12) == 0)
+			hv_name = "Xen";
+		else
+			hv_name = "unknown";
 
-	if (cai->cai_string != NULL) {
-		aprint_verbose("%s ", cai->cai_string);
-	} else {
-		(void)humanize_number(human_num, sizeof(human_num),
-			cai->cai_totalsize, "B", HN_AUTOSCALE, HN_NOSPACE);
-		aprint_verbose("%s %dB/line ", human_num, cai->cai_linesize);
-	}
-	switch (cai->cai_associativity) {
-	case    0:
-		aprint_verbose("disabled");
-		break;
-	case    1:
-		aprint_verbose("direct-mapped");
-		break;
-	case 0xff:
-		aprint_verbose("fully associative");
-		break;
-	default:
-		aprint_verbose("%d-way", cai->cai_associativity);
-		break;
+		printf("%s: Running on hypervisor: %s\n", cpuname, hv_name);
 	}
-	return ", ";
 }
 
-static const char *
-print_tlb_config(struct cpu_info *ci, int cache_tag, const char *name,
-    const char *sep)
+static void
+cpu_probe_features(struct cpu_info *ci)
 {
-	struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
-	char human_num[HUMAN_BUFSIZE];
-
-	if (cai->cai_totalsize == 0)
-		return sep;
+	const struct cpu_cpuid_nameclass *cpup = NULL;
+	unsigned int i;
 
-	if (sep == NULL)
-		aprint_verbose_dev(ci->ci_dev, "");
-	else
-		aprint_verbose("%s", sep);
-	if (name != NULL)
-		aprint_verbose("%s ", name);
+	if (ci->ci_cpuid_level < 1)
+		return;
 
-	if (cai->cai_string != NULL) {
-		aprint_verbose("%s", cai->cai_string);
-	} else {
-		(void)humanize_number(human_num, sizeof(human_num),
-			cai->cai_linesize, "B", HN_AUTOSCALE, HN_NOSPACE);
-		aprint_verbose("%d %s entries ", cai->cai_totalsize,
-		    human_num);
-		switch (cai->cai_associativity) {
-		case 0:
-			aprint_verbose("disabled");
-			break;
-		case 1:
-			aprint_verbose("direct-mapped");
-			break;
-		case 0xff:
-			aprint_verbose("fully associative");
-			break;
-		default:
-			aprint_verbose("%d-way", cai->cai_associativity);
+	for (i = 0; i < __arraycount(i386_cpuid_cpus); i++) {
+		if (!strncmp((char *)ci->ci_vendor,
+		    i386_cpuid_cpus[i].cpu_id, 12)) {
+			cpup = &i386_cpuid_cpus[i];
 			break;
 		}
 	}
-	return ", ";
-}
-
-static const struct x86_cache_info *
-cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc)
-{
-	int i;
 
-	for (i = 0; cai[i].cai_desc != 0; i++) {
-		if (cai[i].cai_desc == desc)
-			return (&cai[i]);
-	}
+	if (cpup == NULL)
+		return;
 
-	return (NULL);
-}
+	i = ci->ci_family - CPU_MINFAMILY;
 
-static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = 
-    AMD_L2CACHE_INFO;
+	if (i >= __arraycount(cpup->cpu_family))
+		i = __arraycount(cpup->cpu_family) - 1;
 
-static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] = 
-    AMD_L3CACHE_INFO;
+	if (cpup->cpu_family[i].cpu_probe == NULL)
+		return;
+
+	(*cpup->cpu_family[i].cpu_probe)(ci);
+}
 
 static void
-amd_cpu_cacheinfo(struct cpu_info *ci)
+print_bits(const char *cpuname, const char *hdr, const char *fmt, uint32_t val)
 {
-	const struct x86_cache_info *cp;
-	struct x86_cache_info *cai;
-	int family, model;
-	u_int descs[4];
-	u_int lfunc;
+	char buf[32 * 16];
+	char *bp;
 
-	family = (ci->ci_signature >> 8) & 15;
-	model = CPUID2MODEL(ci->ci_signature);
+#define	MAX_LINE_LEN	79	/* get from command arg or 'stty cols' ? */
 
-	/*
-	 * K5 model 0 has none of this info.
-	 */
-	if (family == 5 && model == 0)
+	if (val == 0 || fmt == NULL)
 		return;
 
-	/*
-	 * Get extended values for K8 and up.
-	 */
-	if (family == 0xf) {
-		family += CPUID2EXTFAMILY(ci->ci_signature);
-		model += CPUID2EXTMODEL(ci->ci_signature);
+	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;
 	}
+}
 
-	/*
-	 * Determine the largest extended function value.
-	 */
-	x86_cpuid(0x80000000, descs);
-	lfunc = descs[0];
+static void
+identifycpu_cpuids(struct cpu_info *ci)
+{
+	const char *cpuname = ci->ci_dev;
+	u_int lp_max = 1;	/* logical processors per package */
+	u_int smt_max;		/* smt per core */
+	u_int core_max = 1;	/* core per package */
+	u_int smt_bits, core_bits;
+	uint32_t descs[4];
 
-	/*
-	 * Determine L1 cache/TLB info.
-	 */
-	if (lfunc < 0x80000005) {
-		/* No L1 cache info available. */
+	aprint_verbose("%s: Initial APIC ID %u\n", cpuname, ci->ci_initapicid);
+	ci->ci_packageid = ci->ci_initapicid;
+	ci->ci_coreid = 0;
+	ci->ci_smtid = 0;
+	if (cpu_vendor != CPUVENDOR_INTEL) {
 		return;
 	}
 
-	x86_cpuid(0x80000005, descs);
-
 	/*
-	 * K6-III and higher have large page TLBs.
+	 * 253668.pdf 7.10.2
 	 */
-	if ((family == 5 && model >= 9) || family >= 6) {
-		cai = &ci->ci_cinfo[CAI_ITLB2];
-		cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
-		cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
-		cai->cai_linesize = largepagesize;
 
-		cai = &ci->ci_cinfo[CAI_DTLB2];
-		cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
-		cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
-		cai->cai_linesize = largepagesize;
+	if ((ci->ci_feat_val[0] & CPUID_HTT) != 0) {
+		x86_cpuid(1, descs);
+		lp_max = (descs[1] >> 16) & 0xff;
+	}
+	if (ci->ci_cpuid_level >= 4) {
+		x86_cpuid2(4, 0, descs);
+		core_max = (descs[0] >> 26) + 1;
+	}
+	assert(lp_max >= core_max);
+	smt_max = lp_max / core_max;
+	smt_bits = ilog2(smt_max - 1) + 1;
+	core_bits = ilog2(core_max - 1) + 1;
+	if (smt_bits + core_bits) {
+		ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits);
 	}
+	aprint_verbose("%s: Cluster/Package ID %u\n", cpuname,
+	    ci->ci_packageid);
+	if (core_bits) {
+		u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1);
 
-	cai = &ci->ci_cinfo[CAI_ITLB];
-	cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
-	cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
-	cai->cai_linesize = (4 * 1024);
+		ci->ci_coreid =
+		    __SHIFTOUT(ci->ci_initapicid, core_mask);
+		aprint_verbose("%s: Core ID %u\n", cpuname, ci->ci_coreid);
+	}
+	if (smt_bits) {
+		u_int smt_mask = __BITS((int)0, (int)(smt_bits - 1));
 
-	cai = &ci->ci_cinfo[CAI_DTLB];
-	cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
-	cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
-	cai->cai_linesize = (4 * 1024);
+		ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask);
+		aprint_verbose("%s: SMT ID %u\n", cpuname, ci->ci_smtid);
+	}
+}
 
-	cai = &ci->ci_cinfo[CAI_DCACHE];
-	cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
-	cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
-	cai->cai_linesize = AMD_L1_ECX_DC_LS(descs[2]);
+void
+identifycpu(const char *cpuname)
+{
+	const char *name = "", *modifier, *vendorname, *brand = "";
+	int class = CPUCLASS_386;
+	unsigned int i;
+	int modif, family;
+	const struct cpu_cpuid_nameclass *cpup = NULL;
+	const struct cpu_cpuid_family *cpufam;
+	struct cpu_info *ci, cistore;
+	u_int descs[4];
+	size_t sz;
 
-	cai = &ci->ci_cinfo[CAI_ICACHE];
-	cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
-	cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
-	cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
+	ci = &cistore;
+	cpu_probe_base_features(ci, cpuname);
+	aprint_verbose("%s: highest basic info %08x\n", cpuname,
+	    ci->ci_cpuid_level);
+	if (verbose) {
+		int bf;
+		
+		for (bf = 0; bf <= ci->ci_cpuid_level; bf++) {
+			x86_cpuid(bf, descs);
+			printf("%s: %08x: %08x %08x %08x %08x\n", cpuname,
+			    bf, descs[0], descs[1], descs[2], descs[3]);
+		}
+	}
+	if (ci->ci_cpuid_extlevel >=  0x80000000)
+		aprint_verbose("%s: highest extended info %08x\n", cpuname,
+		    ci->ci_cpuid_extlevel);
+	if (verbose) {
+		unsigned int ef;
+
+		for (ef = 0x80000000; ef <= ci->ci_cpuid_extlevel; ef++) {
+			x86_cpuid(ef, descs);
+			printf("%s: %08x: %08x %08x %08x %08x\n", cpuname,
+			    ef, descs[0], descs[1], descs[2], descs[3]);
+		}
+	}
 
-	/*
-	 * Determine L2 cache/TLB info.
-	 */
-	if (lfunc < 0x80000006) {
-		/* No L2 cache info available. */
-		return;
+	cpu_probe_hv_features(ci, cpuname);
+	cpu_probe_features(ci);
+
+	if (ci->ci_cpu_type >= 0) {
+		/* Old pre-cpuid instruction cpu */
+		if (ci->ci_cpu_type >= (int)__arraycount(i386_nocpuid_cpus))
+			errx(1, "unknown cpu type %d", ci->ci_cpu_type);
+		name = i386_nocpuid_cpus[ci->ci_cpu_type].cpu_name;
+		cpu_vendor = i386_nocpuid_cpus[ci->ci_cpu_type].cpu_vendor;
+		vendorname = i386_nocpuid_cpus[ci->ci_cpu_type].cpu_vendorname;
+		class = i386_nocpuid_cpus[ci->ci_cpu_type].cpu_class;
+		ci->ci_info = i386_nocpuid_cpus[ci->ci_cpu_type].cpu_info;
+		modifier = "";
+	} else {
+		/* CPU which support cpuid instruction */
+		modif = (ci->ci_signature >> 12) & 0x3;
+		family = ci->ci_family;
+		if (family < CPU_MINFAMILY)
+			errx(1, "identifycpu: strange family value");
+		if (family > CPU_MAXFAMILY)
+			family = CPU_MAXFAMILY;
+
+		for (i = 0; i < __arraycount(i386_cpuid_cpus); i++) {
+			if (!strncmp((char *)ci->ci_vendor,
+			    i386_cpuid_cpus[i].cpu_id, 12)) {
+				cpup = &i386_cpuid_cpus[i];
+				break;
+			}
+		}
+
+		if (cpup == NULL) {
+			cpu_vendor = CPUVENDOR_UNKNOWN;
+			if (ci->ci_vendor[0] != '\0')
+				vendorname = (char *)&ci->ci_vendor[0];
+			else
+				vendorname = "Unknown";
+			class = family - 3;
+			modifier = "";
+			name = "";
+			ci->ci_info = NULL;
+		} else {
+			cpu_vendor = cpup->cpu_vendor;
+			vendorname = cpup->cpu_vendorname;
+			modifier = modifiers[modif];
+			cpufam = &cpup->cpu_family[family - CPU_MINFAMILY];
+			name = cpufam->cpu_models[ci->ci_model];
+			if (name == NULL || *name == '\0')
+			    name = cpufam->cpu_model_default;
+			class = cpufam->cpu_class;
+			ci->ci_info = cpufam->cpu_info;
+
+			if (cpu_vendor == CPUVENDOR_INTEL) {
+				if (ci->ci_family == 6 && ci->ci_model >= 5) {
+					const char *tmp;
+					tmp = intel_family6_name(ci);
+					if (tmp != NULL)
+						name = tmp;
+				}
+				if (ci->ci_family == 15 &&
+				    ci->ci_brand_id <
+				    __arraycount(i386_intel_brand) &&
+				    i386_intel_brand[ci->ci_brand_id])
+					name =
+					     i386_intel_brand[ci->ci_brand_id];
+			}
+
+			if (cpu_vendor == CPUVENDOR_AMD) {
+				if (ci->ci_family == 6 && ci->ci_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;
+				}
+				if (CPUID2FAMILY(ci->ci_signature) == 0xf) {
+					/* Identify AMD64 CPU names.  */
+					const char *tmp;
+					tmp = amd_amd64_name(ci);
+					if (tmp != NULL)
+						name = tmp;
+				}
+			}
+			
+			if (cpu_vendor == CPUVENDOR_IDT && ci->ci_family >= 6)
+				vendorname = "VIA";
+		}
 	}
 
-	x86_cpuid(0x80000006, descs);
+	ci->ci_cpu_class = class;
 
-	cai = &ci->ci_cinfo[CAI_L2_ITLB];
-	cai->cai_totalsize = AMD_L2_EBX_IUTLB_ENTRIES(descs[1]);
-	cai->cai_associativity = AMD_L2_EBX_IUTLB_ASSOC(descs[1]);
-	cai->cai_linesize = (4 * 1024);
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+	sz = sizeof(ci->ci_tsc_freq);
+	(void)sysctlbyname("machdep.tsc_freq", &ci->ci_tsc_freq, &sz, NULL, 0);
+	sz = sizeof(use_pae);
+	(void)sysctlbyname("machdep.pae", &use_pae, &sz, NULL, 0);
+	largepagesize = (use_pae ? 2 * 1024 * 1024 : 4 * 1024 * 1024);
 
-	cai = &ci->ci_cinfo[CAI_L2_ITLB2];
-	cai->cai_totalsize = AMD_L2_EAX_IUTLB_ENTRIES(descs[0]);
-	cai->cai_associativity = AMD_L2_EAX_IUTLB_ASSOC(descs[0]);
-	cai->cai_linesize = largepagesize;
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+	/*
+	 * 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);
 
-	cai = &ci->ci_cinfo[CAI_L2_DTLB];
-	cai->cai_totalsize = AMD_L2_EBX_DTLB_ENTRIES(descs[1]);
-	cai->cai_associativity = AMD_L2_EBX_DTLB_ASSOC(descs[1]);
-	cai->cai_linesize = (4 * 1024);
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+	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]);
 
-	cai = &ci->ci_cinfo[CAI_L2_DTLB2];
-	cai->cai_totalsize = AMD_L2_EAX_DTLB_ENTRIES(descs[0]);
-	cai->cai_associativity = AMD_L2_EAX_DTLB_ASSOC(descs[0]);
-	cai->cai_linesize = largepagesize;
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+	if (ci->ci_tsc_freq != 0)
+		aprint_normal(", %ju.%02ju MHz",
+		    ((uintmax_t)ci->ci_tsc_freq + 4999) / 1000000,
+		    (((uintmax_t)ci->ci_tsc_freq + 4999) / 10000) % 100);
+	aprint_normal("\n");
 
-	cai = &ci->ci_cinfo[CAI_L2CACHE];
-	cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
-	cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
-	cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
+	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 %#x)", ci->ci_signature);
+	aprint_normal("\n");
 
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+	if (ci->ci_info)
+		(*ci->ci_info)(ci);
 
 	/*
-	 * Determine L3 cache info on AMD Family 10h and newer processors
+	 * display CPU feature flags
 	 */
-	if (family >= 0x10) {
-		cai = &ci->ci_cinfo[CAI_L3CACHE];
-		cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]);
-		cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]);
-		cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]);
 
-		cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info,
-		    cai->cai_associativity);
-		if (cp != NULL)
-			cai->cai_associativity = cp->cai_associativity;
-		else
-			cai->cai_associativity = 0;	/* XXX Unkn/Rsvd */
+	print_bits(cpuname, "features", CPUID_FLAGS1, ci->ci_feat_val[0]);
+	print_bits(cpuname, "features1", CPUID2_FLAGS1, ci->ci_feat_val[1]);
+
+	/* 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());
+	}
+
+	x86_print_cache_and_tlb_info(ci);
+
+	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,
+		    ci->ci_cpu_serial[1] / 65536, ci->ci_cpu_serial[1] % 65536,
+		    ci->ci_cpu_serial[2] / 65536, ci->ci_cpu_serial[2] % 65536);
+	}
+
+	if (ci->ci_cpu_class == CPUCLASS_386) {
+		errx(1, "NetBSD requires an 80486 or later processor");
+	}
+
+	if (ci->ci_cpu_type == CPU_486DLC) {
+#ifndef CYRIX_CACHE_WORKS
+		aprint_error("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
+#else
+#ifndef CYRIX_CACHE_REALLY_WORKS
+		aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
+#else
+		aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
+#endif
+#endif
 	}
 
 	/*
-	 * Determine 1GB TLB info.
+	 * Everything past this point requires a Pentium or later.
 	 */
-	if (lfunc < 0x80000019) {
-		/* No 1GB TLB info available. */
+	if (ci->ci_cpuid_level < 0)
 		return;
-	}
 
-	x86_cpuid(0x80000019, descs);
+	identifycpu_cpuids(ci);
 
-	cai = &ci->ci_cinfo[CAI_L1_1GBITLB];
-	cai->cai_totalsize = AMD_L1_1GB_EAX_IUTLB_ENTRIES(descs[0]);
-	cai->cai_associativity = AMD_L1_1GB_EAX_IUTLB_ASSOC(descs[0]);
-	cai->cai_linesize = (1024 * 1024 * 1024);
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+#ifdef INTEL_CORETEMP
+	if (cpu_vendor == CPUVENDOR_INTEL && ci->ci_cpuid_level >= 0x06)
+		coretemp_register(ci);
+#endif
 
-	cai = &ci->ci_cinfo[CAI_L1_1GBDTLB];
-	cai->cai_totalsize = AMD_L1_1GB_EAX_DTLB_ENTRIES(descs[0]);
-	cai->cai_associativity = AMD_L1_1GB_EAX_DTLB_ASSOC(descs[0]);
-	cai->cai_linesize = (1024 * 1024 * 1024);
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+	if (cpu_vendor == CPUVENDOR_AMD) {
+		uint32_t data[4];
 
-	cai = &ci->ci_cinfo[CAI_L2_1GBITLB];
-	cai->cai_totalsize = AMD_L2_1GB_EBX_IUTLB_ENTRIES(descs[1]);
-	cai->cai_associativity = AMD_L2_1GB_EBX_IUTLB_ASSOC(descs[1]);
-	cai->cai_linesize = (1024 * 1024 * 1024);
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
+		x86_cpuid(0x80000000, data);
+		if (data[0] >= 0x80000007)
+			powernow_probe(ci);
 
-	cai = &ci->ci_cinfo[CAI_L2_1GBDTLB];
-	cai->cai_totalsize = AMD_L2_1GB_EBX_DUTLB_ENTRIES(descs[1]);
-	cai->cai_associativity = AMD_L2_1GB_EBX_DUTLB_ASSOC(descs[1]);
-	cai->cai_linesize = (1024 * 1024 * 1024);
-	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
-	    cai->cai_associativity);
-	if (cp != NULL)
-		cai->cai_associativity = cp->cai_associativity;
-	else
-		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
-}
+		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]);
+			print_bits(cpuname, "SVM features", CPUID_AMD_SVM_FLAGS,
+				   data[3]);
+		}
+	} else if (cpu_vendor == CPUVENDOR_INTEL) {
+		uint32_t data[4];
+		int32_t bi_index;
 
-static void
-via_cpu_cacheinfo(struct cpu_info *ci)
-{
-	struct x86_cache_info *cai;
-	int family, model, stepping;
-	u_int descs[4];
-	u_int lfunc;
+		for (bi_index = 1; bi_index <= ci->ci_cpuid_level; bi_index++) {
+			x86_cpuid(bi_index, data);
+			switch (bi_index) {
+			case 6:
+				print_bits(cpuname, "DSPM-eax",
+				    CPUID_DSPM_FLAGS, data[0]);
+				print_bits(cpuname, "DSPM-ecx",
+				    CPUID_DSPM_FLAGS1, data[2]);
+				break;
+			case 7:
+				aprint_verbose("%s: SEF highest subleaf %08x\n",
+				    cpuname, data[0]);
+				print_bits(cpuname, "SEF-main", CPUID_SEF_FLAGS,
+				    data[1]);
+				break;
+#if 0
+			default:
+				aprint_verbose("%s: basic %08x-eax %08x\n",
+				    cpuname, bi_index, data[0]);
+				aprint_verbose("%s: basic %08x-ebx %08x\n",
+				    cpuname, bi_index, data[1]);
+				aprint_verbose("%s: basic %08x-ecx %08x\n",
+				    cpuname, bi_index, data[2]);
+				aprint_verbose("%s: basic %08x-edx %08x\n",
+				    cpuname, bi_index, data[3]);
+				break;
+#endif
+			}
+		}
+	}
 
-	family = (ci->ci_signature >> 8) & 15;
-	model = CPUID2MODEL(ci->ci_signature);
-	stepping = CPUID2STEPPING(ci->ci_signature);
+#ifdef INTEL_ONDEMAND_CLOCKMOD
+	clockmod_init();
+#endif
 
-	/*
-	 * Determine the largest extended function value.
-	 */
-	x86_cpuid(0x80000000, descs);
-	lfunc = descs[0];
+	aprint_normal_dev(ci->ci_dev, "family %02x model %02x stepping %02x\n",
+	    ci->ci_family, ci->ci_model, CPUID2STEPPING(ci->ci_signature));
+}
 
-	/*
-	 * Determine L1 cache/TLB info.
-	 */
-	if (lfunc < 0x80000005) {
-		/* No L1 cache info available. */
-		return;
+static const struct x86_cache_info *
+cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc)
+{
+	int i;
+
+	for (i = 0; cai[i].cai_desc != 0; i++) {
+		if (cai[i].cai_desc == desc)
+			return (&cai[i]);
 	}
 
-	x86_cpuid(0x80000005, descs);
+	return (NULL);
+}
 
-	cai = &ci->ci_cinfo[CAI_ITLB];
-	cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]);
-	cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]);
-	cai->cai_linesize = (4 * 1024);
+static const char *
+print_cache_config(struct cpu_info *ci, int cache_tag, const char *name,
+    const char *sep)
+{
+	struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
+	char human_num[HUMAN_BUFSIZE];
 
-	cai = &ci->ci_cinfo[CAI_DTLB];
-	cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]);
-	cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]);
-	cai->cai_linesize = (4 * 1024);
+	if (cai->cai_totalsize == 0)
+		return sep;
 
-	cai = &ci->ci_cinfo[CAI_DCACHE];
-	cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]);
-	cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]);
-	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]);
-	if (model == 9 && stepping == 8) {
-		/* Erratum: stepping 8 reports 4 when it should be 2 */
-		cai->cai_associativity = 2;
-	}
+	if (sep == NULL)
+		aprint_verbose_dev(ci->ci_dev, "");
+	else
+		aprint_verbose("%s", sep);
+	if (name != NULL)
+		aprint_verbose("%s ", name);
 
-	cai = &ci->ci_cinfo[CAI_ICACHE];
-	cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]);
-	cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]);
-	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]);
-	if (model == 9 && stepping == 8) {
-		/* Erratum: stepping 8 reports 4 when it should be 2 */
-		cai->cai_associativity = 2;
+	if (cai->cai_string != NULL) {
+		aprint_verbose("%s ", cai->cai_string);
+	} else {
+		(void)humanize_number(human_num, sizeof(human_num),
+			cai->cai_totalsize, "B", HN_AUTOSCALE, HN_NOSPACE);
+		aprint_verbose("%s %dB/line ", human_num, cai->cai_linesize);
 	}
-
-	/*
-	 * Determine L2 cache/TLB info.
-	 */
-	if (lfunc < 0x80000006) {
-		/* No L2 cache info available. */
-		return;
+	switch (cai->cai_associativity) {
+	case    0:
+		aprint_verbose("disabled");
+		break;
+	case    1:
+		aprint_verbose("direct-mapped");
+		break;
+	case 0xff:
+		aprint_verbose("fully associative");
+		break;
+	default:
+		aprint_verbose("%d-way", cai->cai_associativity);
+		break;
 	}
+	return ", ";
+}
 
-	x86_cpuid(0x80000006, descs);
+static const char *
+print_tlb_config(struct cpu_info *ci, int cache_tag, const char *name,
+    const char *sep)
+{
+	struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
+	char human_num[HUMAN_BUFSIZE];
 
-	cai = &ci->ci_cinfo[CAI_L2CACHE];
-	if (model >= 9) {
-		cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]);
-		cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]);
-		cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]);
+	if (cai->cai_totalsize == 0)
+		return sep;
+
+	if (sep == NULL)
+		aprint_verbose_dev(ci->ci_dev, "");
+	else
+		aprint_verbose("%s", sep);
+	if (name != NULL)
+		aprint_verbose("%s ", name);
+
+	if (cai->cai_string != NULL) {
+		aprint_verbose("%s", cai->cai_string);
 	} else {
-		cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]);
-		cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]);
-		cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]);
+		(void)humanize_number(human_num, sizeof(human_num),
+			cai->cai_linesize, "B", HN_AUTOSCALE, HN_NOSPACE);
+		aprint_verbose("%d %s entries ", cai->cai_totalsize,
+		    human_num);
+		switch (cai->cai_associativity) {
+		case 0:
+			aprint_verbose("disabled");
+			break;
+		case 1:
+			aprint_verbose("direct-mapped");
+			break;
+		case 0xff:
+			aprint_verbose("fully associative");
+			break;
+		default:
+			aprint_verbose("%d-way", cai->cai_associativity);
+			break;
+		}
 	}
+	return ", ";
 }
 
 static void
-x86_print_cacheinfo(struct cpu_info *ci)
+x86_print_cache_and_tlb_info(struct cpu_info *ci)
 {
-	const char *sep;
+	const char *sep = NULL;
 
 	if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 ||
 	    ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) {
@@ -1938,6 +2092,12 @@ x86_print_cacheinfo(struct cpu_info *ci)
 		if (sep != NULL)
 			aprint_verbose("\n");
 	}
+	if (ci->ci_cinfo[CAI_PREFETCH].cai_linesize != 0) {
+		aprint_verbose_dev(ci->ci_dev, "%dB prefetching",
+			ci->ci_cinfo[CAI_PREFETCH].cai_linesize);
+		if (sep != NULL)
+			aprint_verbose("\n");
+	}
 	if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) {
 		sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL);
 		sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep);
@@ -1962,23 +2122,33 @@ x86_print_cacheinfo(struct cpu_info *ci)
 		if (sep != NULL)
 			aprint_verbose("\n");
 	}
+	if (ci->ci_cinfo[CAI_L2_STLB].cai_totalsize != 0) {
+		sep = print_tlb_config(ci, CAI_L2_STLB, "L2 STLB", NULL);
+		sep = print_tlb_config(ci, CAI_L2_STLB2, NULL, sep);
+		if (sep != NULL)
+			aprint_verbose("\n");
+	}
 	if (ci->ci_cinfo[CAI_L1_1GBITLB].cai_totalsize != 0) {
-		sep = print_tlb_config(ci, CAI_L1_1GBITLB, "L1 1GB page ITLB", NULL);
+		sep = print_tlb_config(ci, CAI_L1_1GBITLB, "L1 1GB page ITLB",
+		    NULL);
 		if (sep != NULL)
 			aprint_verbose("\n");
 	}
 	if (ci->ci_cinfo[CAI_L1_1GBDTLB].cai_totalsize != 0) {
-		sep = print_tlb_config(ci, CAI_L1_1GBDTLB, "L1 1GB page DTLB", NULL);
+		sep = print_tlb_config(ci, CAI_L1_1GBDTLB, "L1 1GB page DTLB",
+		    NULL);
 		if (sep != NULL)
 			aprint_verbose("\n");
 	}
 	if (ci->ci_cinfo[CAI_L2_1GBITLB].cai_totalsize != 0) {
-		sep = print_tlb_config(ci, CAI_L2_1GBITLB, "L2 1GB page ITLB", NULL);
+		sep = print_tlb_config(ci, CAI_L2_1GBITLB, "L2 1GB page ITLB",
+		    NULL);
 		if (sep != NULL)
 			aprint_verbose("\n");
 	}
 	if (ci->ci_cinfo[CAI_L2_1GBDTLB].cai_totalsize != 0) {
-		sep = print_tlb_config(ci, CAI_L2_1GBDTLB, "L2 1GB page DTLB", NULL);
+		sep = print_tlb_config(ci, CAI_L2_1GBDTLB, "L2 1GB page DTLB",
+		    NULL);
 		if (sep != NULL)
 			aprint_verbose("\n");
 	}

Index: src/usr.sbin/cpuctl/arch/x86_64-asm.S
diff -u src/usr.sbin/cpuctl/arch/x86_64-asm.S:1.2 src/usr.sbin/cpuctl/arch/x86_64-asm.S:1.2.20.1
--- src/usr.sbin/cpuctl/arch/x86_64-asm.S:1.2	Sun Oct 19 15:22:17 2008
+++ src/usr.sbin/cpuctl/arch/x86_64-asm.S	Fri Jan 16 08:30:50 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_64-asm.S,v 1.2 2008/10/19 15:22:17 christos Exp $	*/
+/*	$NetBSD: x86_64-asm.S,v 1.2.20.1 2015/01/16 08:30:50 snj Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -28,15 +28,6 @@
 
 #include <machine/asm.h>
 
-	.data
-
-_C_LABEL(cpu):
-	.long	0
-	.globl	_C_LABEL(cpu)
-_C_LABEL(cpu_info_level):
-	.long	-1
-	.globl	_C_LABEL(cpu_info_level)
-
 	.text
 
 ENTRY(x86_cpuid2)
@@ -52,9 +43,10 @@ ENTRY(x86_cpuid2)
 	popq	%rbx
 	ret
 
+ENTRY(x86_xgetbv)
+	xgetbv
+	ret
+
 ENTRY(x86_identify)
-	pushq	%rbx
-	cpuid
-	movl	%eax, PIC_GOT(_C_LABEL(cpu_info_level))
-	popq	%rbx
+	movl	$-1,%eax
 	ret

Reply via email to