changeset 9482:42f3d60af7ca onnv_114

6770233 New model ID for Istanbul processor 6672305 Need to support Griffin processors 6824550 AMD G34 processors need cpuid support Contributed by Boris Ostrovsky <boris.ostrovsky@amd.com>
author Kuriakose Kuruvilla <Kuriakose.Kuruvilla@Sun.COM>
date Mon, 27 Apr 2009 23:10:26 -0700
parents b25f8de94abf
children 74ff44a6bba1
files usr/src/cmd/psrinfo/psrinfo.pl usr/src/uts/common/os/cpu.c usr/src/uts/i86pc/os/cmi_hw.c usr/src/uts/i86pc/os/cpuid.c usr/src/uts/i86pc/os/cpuid_subr.c usr/src/uts/intel/io/mc-amd/mcamd_drv.c usr/src/uts/intel/sys/cpu_module.h usr/src/uts/intel/sys/x86_archext.h
diffstat 8 files changed, 250 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/psrinfo/psrinfo.pl	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/cmd/psrinfo/psrinfo.pl	Mon Apr 27 23:10:26 2009 -0700
@@ -20,11 +20,9 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
 # psrinfo: displays information about processors
 #
 # See detailed comment in the end of this file.
@@ -686,6 +684,7 @@
 			my $brand = $cpu->{brand} ||  gettext("(unknown)");
 			my $impl = $cpu->{implementation} ||
 			  gettext("(unknown)");
+			my $socket = $cpu->{socket_type};
 			#
 			# Remove cpuid and chipid information from
 			# implementation string and print it.
@@ -702,7 +701,10 @@
 				       $cname, $ncpus, $cpu_name;
 				print "($cl)\n";
 				print "  $impl\n" if $impl;
-				print "\t$brand\n" if $brand;
+				print "\t$brand" if $brand;
+				print "\t[ Socket: $socket ]" if $socket &&
+				  $socket ne "Unknown";
+				print "\n";
 			} else {
 				# Get child count
 				my $nchildren =
--- a/usr/src/uts/common/os/cpu.c	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/uts/common/os/cpu.c	Mon Apr 27 23:10:26 2009 -0700
@@ -2166,6 +2166,7 @@
 	kstat_named_t ci_ncoreperchip;
 	kstat_named_t ci_max_cstates;
 	kstat_named_t ci_curr_cstate;
+	kstat_named_t ci_sktstr;
 #endif
 } cpu_info_template = {
 	{ "state",			KSTAT_DATA_CHAR },
@@ -2194,6 +2195,7 @@
 	{ "ncore_per_chip",		KSTAT_DATA_INT32 },
 	{ "supported_max_cstates",	KSTAT_DATA_INT32 },
 	{ "current_cstate",		KSTAT_DATA_INT32 },
+	{ "socket_type",		KSTAT_DATA_STRING },
 #endif
 };
 
@@ -2265,6 +2267,8 @@
 	cpu_info_template.ci_pkg_core_id.value.l = cpuid_get_pkgcoreid(cp);
 	cpu_info_template.ci_max_cstates.value.l = cp->cpu_m.max_cstates;
 	cpu_info_template.ci_curr_cstate.value.l = cp->cpu_m.curr_cstate;
+	kstat_named_setstr(&cpu_info_template.ci_sktstr,
+	    cpuid_getsocketstr(cp));
 #endif
 
 	return (0);
--- a/usr/src/uts/i86pc/os/cmi_hw.c	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/uts/i86pc/os/cmi_hw.c	Mon Apr 27 23:10:26 2009 -0700
@@ -95,6 +95,8 @@
 	uint32_t (*cmio_chiprev)(cmi_hdl_impl_t *);
 	const char *(*cmio_chiprevstr)(cmi_hdl_impl_t *);
 	uint32_t (*cmio_getsockettype)(cmi_hdl_impl_t *);
+	const char *(*cmio_getsocketstr)(cmi_hdl_impl_t *);
+
 	id_t (*cmio_logical_id)(cmi_hdl_impl_t *);
 	/*
 	 * These ops are optional in an implementation.
@@ -617,6 +619,12 @@
 	return (cpuid_getsockettype(HDLPRIV(hdl)));
 }
 
+static const char *
+ntv_getsocketstr(cmi_hdl_impl_t *hdl)
+{
+	return (cpuid_getsocketstr(HDLPRIV(hdl)));
+}
+
 static id_t
 ntv_logical_id(cmi_hdl_impl_t *hdl)
 {
@@ -876,6 +884,15 @@
 	    xpv_model(hdl), xpv_stepping(hdl)));
 }
 
+extern const char *_cpuid_sktstr(uint_t, uint_t, uint_t, uint_t);
+
+static const char *
+xpv_getsocketstr(cmi_hdl_impl_t *hdl)
+{
+	return (_cpuid_sktstr(xpv_vendor(hdl), xpv_family(hdl),
+	    xpv_model(hdl), xpv_stepping(hdl)));
+}
+
 static id_t
 xpv_logical_id(cmi_hdl_impl_t *hdl)
 {
@@ -1391,6 +1408,7 @@
 CMI_HDL_OPFUNC(chiprev, uint32_t)
 CMI_HDL_OPFUNC(chiprevstr, const char *)
 CMI_HDL_OPFUNC(getsockettype, uint32_t)
+CMI_HDL_OPFUNC(getsocketstr, const char *)
 CMI_HDL_OPFUNC(logical_id, id_t)
 
 boolean_t
@@ -1722,6 +1740,7 @@
 	xpv_chiprev,		/* cmio_chiprev */
 	xpv_chiprevstr,		/* cmio_chiprevstr */
 	xpv_getsockettype,	/* cmio_getsockettype */
+	xpv_getsocketstr,	/* cmio_getsocketstr */
 	xpv_logical_id,		/* cmio_logical_id */
 	NULL,			/* cmio_getcr4 */
 	NULL,			/* cmio_setcr4 */
@@ -1747,6 +1766,7 @@
 	ntv_chiprev,		/* cmio_chiprev */
 	ntv_chiprevstr,		/* cmio_chiprevstr */
 	ntv_getsockettype,	/* cmio_getsockettype */
+	ntv_getsocketstr,	/* cmio_getsocketstr */
 	ntv_logical_id,		/* cmio_logical_id */
 	ntv_getcr4,		/* cmio_getcr4 */
 	ntv_setcr4,		/* cmio_setcr4 */
--- a/usr/src/uts/i86pc/os/cpuid.c	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/uts/i86pc/os/cpuid.c	Mon Apr 27 23:10:26 2009 -0700
@@ -306,6 +306,7 @@
  * file to try and keep people using the expected cpuid_* interfaces.
  */
 extern uint32_t _cpuid_skt(uint_t, uint_t, uint_t, uint_t);
+extern const char *_cpuid_sktstr(uint_t, uint_t, uint_t, uint_t);
 extern uint32_t _cpuid_chiprev(uint_t, uint_t, uint_t, uint_t);
 extern const char *_cpuid_chiprevstr(uint_t, uint_t, uint_t, uint_t);
 extern uint_t _cpuid_vendorstr_to_vendorcode(char *);
@@ -495,6 +496,10 @@
 	extern int idle_cpu_prefer_mwait;
 #endif
 
+
+#if !defined(__xpv)
+	determine_platform();
+#endif
 	/*
 	 * Space statically allocated for cpu0, ensure pointer is set
 	 */
@@ -1226,9 +1231,6 @@
 	    cpi->cpi_model, cpi->cpi_step);
 
 pass1_done:
-#if !defined(__xpv)
-	determine_platform();
-#endif
 	cpi->cpi_pass = 1;
 	return (feature);
 }
@@ -2484,6 +2486,24 @@
 	return (cpu->cpu_m.mcpu_cpi->cpi_socket);
 }
 
+const char *
+cpuid_getsocketstr(cpu_t *cpu)
+{
+	static const char *socketstr = NULL;
+	struct cpuid_info *cpi;
+
+	ASSERT(cpuid_checkpass(cpu, 1));
+	cpi = cpu->cpu_m.mcpu_cpi;
+
+	/* Assume that socket types are the same across the system */
+	if (socketstr == NULL)
+		socketstr = _cpuid_sktstr(cpi->cpi_vendor, cpi->cpi_family,
+		    cpi->cpi_model, cpi->cpi_step);
+
+
+	return (socketstr);
+}
+
 int
 cpuid_get_chipid(cpu_t *cpu)
 {
--- a/usr/src/uts/i86pc/os/cpuid_subr.c	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/uts/i86pc/os/cpuid_subr.c	Mon Apr 27 23:10:26 2009 -0700
@@ -20,11 +20,15 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 /*
+ * Portions Copyright 2009 Advanced Micro Devices, Inc.
+ */
+
+/*
  * Support functions that interpret CPUID and similar information.
  * These should not be used from anywhere other than cpuid.c and
  * cmi_hw.c - as such we will not list them in any header file
@@ -46,17 +50,24 @@
 
 #include <sys/types.h>
 #include <sys/systm.h>
+#include <sys/bitmap.h>
 #include <sys/x86_archext.h>
+#include <sys/pci_cfgspace.h>
+#ifdef __xpv
+#include <sys/hypervisor.h>
+#endif
 
 /*
- * AMD family 0xf and family 0x10 socket types.
+ * AMD socket types.
  * First index :
  *		0 for family 0xf, revs B thru E
  *		1 for family 0xf, revs F and G
- *		2 for family 0x10, rev B
- * Second index by (model & 0x3)
+ *		2 for family 0x10
+ *		3 for family 0x11
+ * Second index by (model & 0x3) for family 0fh
+ * or CPUID bits for later families
  */
-static uint32_t amd_skts[3][4] = {
+static uint32_t amd_skts[4][4] = {
 	/*
 	 * Family 0xf revisions B through E
 	 */
@@ -78,19 +89,48 @@
 		X86_SOCKET_AM2		/* 0b11 */
 	},
 	/*
-	 * Family 0x10 revisions A and B
-	 * It is not clear whether, as new sockets release, that
-	 * model & 0x3 will id socket for this family
+	 * Family 0x10
 	 */
 #define	A_SKTS_2			2
 	{
 		X86_SOCKET_F1207,	/* 0b00 */
-		X86_SOCKET_F1207,	/* 0b01 */
-		X86_SOCKET_F1207,	/* 0b10 */
-		X86_SOCKET_F1207,	/* 0b11 */
+		X86_SOCKET_AM,		/* 0b01 */
+		X86_SOCKET_S1g3,	/* 0b10 */
+		X86_SOCKET_G34,		/* 0b11 */
+	},
+
+	/*
+	 * Family 0x11
+	 */
+#define	A_SKTS_3			3
+	{
+		X86_SOCKET_UNKNOWN,	/* 0b00 */
+		X86_SOCKET_UNKNOWN,	/* 0b01 */
+		X86_SOCKET_S1g2,	/* 0b10 */
+		X86_SOCKET_UNKNOWN,	/* 0b11 */
 	}
 };
 
+struct amd_sktmap_s {
+	uint32_t	skt_code;
+	char		sktstr[16];
+};
+static struct amd_sktmap_s amd_sktmap[13] = {
+	{ X86_SOCKET_754,	"754" },
+	{ X86_SOCKET_939,	"939" },
+	{ X86_SOCKET_940,	"940" },
+	{ X86_SOCKET_S1g1,	"S1g1" },
+	{ X86_SOCKET_AM2,	"AM2" },
+	{ X86_SOCKET_F1207,	"F(1207)" },
+	{ X86_SOCKET_S1g2,	"S1g2" },
+	{ X86_SOCKET_S1g3,	"S1g3" },
+	{ X86_SOCKET_AM,	"AM" },
+	{ X86_SOCKET_AM2R2,	"AM2r2" },
+	{ X86_SOCKET_AM3,	"AM3" },
+	{ X86_SOCKET_G34,	"G34" },
+	{ X86_SOCKET_UNKNOWN,	"Unknown" }
+};
+
 /*
  * Table for mapping AMD Family 0xf and AMD Family 0x10 model/stepping
  * combination to chip "revision" and socket type.
@@ -162,9 +202,20 @@
 
 	/*
 	 * Rev C has models 4-6 (depending on L3 cache configuration)
-	 * Give all of model 2 stepping range to rev c.
+	 * Give all of models 4-6 stepping range to rev C.
 	 */
 	{ 0x10, 0x04, 0x06, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_C, "C", A_SKTS_2 },
+
+	/*
+	 * Rev D has models 8 and 9
+	 * Give all of model 8 and 9 stepping range to rev D.
+	 */
+	{ 0x10, 0x08, 0x09, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_D, "D", A_SKTS_2 },
+
+	/*
+	 * =============== AuthenticAMD Family 0x11 ===============
+	 */
+	{ 0x11, 0x03, 0x3, 0x0, 0xf, X86_CHIPREV_AMD_11, "B", A_SKTS_3 },
 };
 
 static void
@@ -175,10 +226,7 @@
 	int found = 0;
 	int i;
 
-	/*
-	 * Currently only AMD family 0xf and family 0x10 use these fields.
-	 */
-	if (family != 0xf && family != 0x10)
+	if (family < 0xf)
 		return;
 
 	for (i = 0, rmp = amd_revmap; i < sizeof (amd_revmap) / sizeof (*rmp);
@@ -191,13 +239,66 @@
 		}
 	}
 
-	if (found) {
-		if (skt_p != NULL)
+	if (!found)
+		return;
+
+	if (chiprev_p != NULL)
+		*chiprev_p = rmp->rm_chiprev;
+	if (chiprevstr_p != NULL)
+		*chiprevstr_p = rmp->rm_chiprevstr;
+
+	if (skt_p != NULL) {
+		int platform;
+
+#ifdef __xpv
+		/* PV guest */
+		if (!is_controldom()) {
+			*skt_p = X86_SOCKET_UNKNOWN;
+			return;
+		}
+#endif
+		platform = get_hwenv();
+
+		if ((platform == HW_XEN_HVM) || (platform == HW_VMWARE)) {
+			*skt_p = X86_SOCKET_UNKNOWN;
+		} else if (family == 0xf) {
 			*skt_p = amd_skts[rmp->rm_sktidx][model & 0x3];
-		if (chiprev_p != NULL)
-			*chiprev_p = rmp->rm_chiprev;
-		if (chiprevstr_p != NULL)
-			*chiprevstr_p = rmp->rm_chiprevstr;
+		} else {
+			/*
+			 * Starting with family 10h, socket type is stored in
+			 * CPUID Fn8000_0001_EBX
+			 */
+			struct cpuid_regs cp;
+			int idx;
+
+			cp.cp_eax = 0x80000001;
+			(void) __cpuid_insn(&cp);
+
+			/* PkgType bits */
+			idx = BITX(cp.cp_ebx, 31, 28);
+
+			if (idx > 3) {
+				/* Reserved bits */
+				*skt_p = X86_SOCKET_UNKNOWN;
+			} else if (family == 0x10 &&
+			    amd_skts[rmp->rm_sktidx][idx] ==
+			    X86_SOCKET_AM) {
+				/*
+				 * Look at Ddr3Mode bit of DRAM Configuration
+				 * High Register to decide whether this is
+				 * AM2r2 (aka AM2+) or AM3.
+				 */
+				uint32_t val;
+
+				val = pci_getl_func(0, 24, 2, 0x94);
+				if (BITX(val, 8, 8))
+					*skt_p = X86_SOCKET_AM3;
+				else
+					*skt_p = X86_SOCKET_AM2R2;
+			} else {
+				*skt_p = amd_skts[rmp->rm_sktidx][idx];
+			}
+		}
 	}
 }
 
@@ -219,6 +320,34 @@
 	return (skt);
 }
 
+const char *
+_cpuid_sktstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
+{
+	const char *sktstr = "Unknown";
+	struct amd_sktmap_s *sktmapp;
+	uint32_t skt = X86_SOCKET_UNKNOWN;
+
+	switch (vendor) {
+	case X86_VENDOR_AMD:
+		synth_amd_info(family, model, step, &skt, NULL, NULL);
+
+		sktmapp = amd_sktmap;
+		while (sktmapp->skt_code != X86_SOCKET_UNKNOWN) {
+			if (sktmapp->skt_code == skt)
+				break;
+			sktmapp++;
+		}
+		sktstr = sktmapp->sktstr;
+		break;
+
+	default:
+		break;
+
+	}
+
+	return (sktstr);
+}
+
 uint32_t
 _cpuid_chiprev(uint_t vendor, uint_t family, uint_t model, uint_t step)
 {
--- a/usr/src/uts/intel/io/mc-amd/mcamd_drv.c	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/uts/intel/io/mc-amd/mcamd_drv.c	Mon Apr 27 23:10:26 2009 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -165,34 +165,39 @@
 	}
 }
 
-#define	NSKT	6
+/*ARGSUSED*/
+static int
+mc_nvl_add_socket_cb(cmi_hdl_t whdl, void *arg1, void *arg2, void *arg3)
+{
+	uint32_t skt = *((uint32_t *)arg1);
+	cmi_hdl_t *hdlp = (cmi_hdl_t *)arg2;
+
+	if (cmi_hdl_getsockettype(whdl) == skt) {
+		cmi_hdl_hold(whdl);	/* short-term hold */
+		*hdlp = whdl;
+		return (CMI_HDL_WALK_DONE);
+	} else {
+		return (CMI_HDL_WALK_NEXT);
+	}
+}
 
 static void
 mc_nvl_add_socket(nvlist_t *nvl, mc_t *mc)
 {
-	const char *s = "Unknown";
-	int i;
+	cmi_hdl_t hdl = NULL;
+	const char *s;
 
-	static const struct {
-		uint32_t type;
-		const char *name;
-	} sktnames[NSKT] = {
-		{ X86_SOCKET_754, "Socket 754" },
-		{ X86_SOCKET_939, "Socket 939" },
-		{ X86_SOCKET_940, "Socket 940" },
-		{ X86_SOCKET_AM2, "Socket AM2" },
-		{ X86_SOCKET_F1207, "Socket F(1207)" },
-		{ X86_SOCKET_S1g1, "Socket S1g1" },
-	};
-
-	for (i = 0; i < NSKT; i++) {
-		if (mc->mc_socket == sktnames[i].type) {
-			s = sktnames[i].name;
-			break;
-		}
-	}
+	cmi_hdl_walk(mc_nvl_add_socket_cb, (void *)&mc->mc_socket,
+	    (void *)&hdl, NULL);
+	if (hdl == NULL)
+		s = "Unknown";  /* no cpu for this chipid found */
+	else
+		s = cmi_hdl_getsocketstr(hdl);
 
 	(void) nvlist_add_string(nvl, "socket", s);
+
+	if (hdl != NULL)
+		cmi_hdl_rele(hdl);
 }
 
 static uint32_t
--- a/usr/src/uts/intel/sys/cpu_module.h	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/uts/intel/sys/cpu_module.h	Mon Apr 27 23:10:26 2009 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -157,6 +157,7 @@
 extern uint32_t cmi_hdl_chiprev(cmi_hdl_t);
 extern const char *cmi_hdl_chiprevstr(cmi_hdl_t);
 extern uint32_t cmi_hdl_getsockettype(cmi_hdl_t);
+extern const char *cmi_hdl_getsocketstr(cmi_hdl_t);
 extern id_t cmi_hdl_logical_id(cmi_hdl_t);
 
 extern int cmi_hdl_online(cmi_hdl_t, int, int *);
--- a/usr/src/uts/intel/sys/x86_archext.h	Tue Apr 28 12:24:30 2009 +0800
+++ b/usr/src/uts/intel/sys/x86_archext.h	Mon Apr 27 23:10:26 2009 -0700
@@ -506,6 +506,15 @@
 	_X86_CHIPREV_MKREV(X86_VENDOR_AMD, 0x10, 0x0002)
 #define	X86_CHIPREV_AMD_10_REV_C \
 	_X86_CHIPREV_MKREV(X86_VENDOR_AMD, 0x10, 0x0004)
+#define	X86_CHIPREV_AMD_10_REV_D \
+	_X86_CHIPREV_MKREV(X86_VENDOR_AMD, 0x10, 0x0008)
+
+/*
+ * Definitions for AMD Family 0x11.
+ */
+#define	X86_CHIPREV_AMD_11 \
+	_X86_CHIPREV_MKREV(X86_VENDOR_AMD, 0x11, 0x0003)
+
 
 /*
  * Various socket/package types, extended as the need to distinguish
@@ -523,7 +532,7 @@
 
 #define	X86_SOCKET_MATCH(s, mask) \
 	(_X86_SOCKET_VENDOR(s) == _X86_SOCKET_VENDOR(mask) && \
-	(_X86_SOCKET_TYPE(s) & _X86_SOCKET_TYPE(mask)) != 0)
+	(_X86_SOCKET_TYPE(s) == _X86_SOCKET_TYPE(mask)))
 
 #define	X86_SOCKET_UNKNOWN 0x0
 	/*
@@ -535,6 +544,12 @@
 #define	X86_SOCKET_S1g1		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000008)
 #define	X86_SOCKET_AM2		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000010)
 #define	X86_SOCKET_F1207	_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000020)
+#define	X86_SOCKET_S1g2		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000030)
+#define	X86_SOCKET_S1g3		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000040)
+#define	X86_SOCKET_AM		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000050)
+#define	X86_SOCKET_AM2R2	_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000060)
+#define	X86_SOCKET_AM3		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000070)
+#define	X86_SOCKET_G34		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000080)
 
 #if !defined(_ASM)
 
@@ -611,6 +626,7 @@
 extern uint32_t cpuid_getchiprev(struct cpu *);
 extern const char *cpuid_getchiprevstr(struct cpu *);
 extern uint32_t cpuid_getsockettype(struct cpu *);
+extern const char *cpuid_getsocketstr(struct cpu *);
 
 extern int cpuid_opteron_erratum(struct cpu *, uint_t);