changeset 12261:52117d41c06e

6930914 Need enhancement of the cmi handle table for Intel EX chip family
author Vuong Nguyen <Vuong.Nguyen@Sun.COM>
date Mon, 26 Apr 2010 16:32:21 -0700
parents 806de32452bd
children 23286d16230d
files usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c usr/src/uts/i86pc/os/cmi_hw.c usr/src/uts/i86pc/os/cpuid.c
diffstat 3 files changed, 158 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c	Mon Apr 26 15:44:36 2010 -0700
+++ b/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c	Mon Apr 26 16:32:21 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <mdb/mdb_modapi.h>
@@ -79,30 +78,22 @@
 };
 
 #define	CMI_MAX_CHIPID_NBITS		6	/* max chipid of 63 */
-#define	CMI_MAX_CORES_PER_CHIP_NBITS	4	/* 16 cores per chip max */
-#define	CMI_MAX_STRANDS_PER_CORE_NBITS	3	/* 8 strands per core max */
 
 #define	CMI_MAX_CHIPID			((1 << (CMI_MAX_CHIPID_NBITS)) - 1)
-#define	CMI_MAX_CORES_PER_CHIP		(1 << CMI_MAX_CORES_PER_CHIP_NBITS)
-#define	CMI_MAX_STRANDS_PER_CORE	(1 << CMI_MAX_STRANDS_PER_CORE_NBITS)
-#define	CMI_MAX_STRANDS_PER_CHIP	(CMI_MAX_CORES_PER_CHIP * \
-					    CMI_MAX_STRANDS_PER_CORE)
-
-#define	CMI_HDL_ARR_IDX_CORE(coreid) \
-	(((coreid) & (CMI_MAX_CORES_PER_CHIP - 1)) << \
-	CMI_MAX_STRANDS_PER_CORE_NBITS)
-
-#define	CMI_HDL_ARR_IDX_STRAND(strandid) \
-	(((strandid) & (CMI_MAX_STRANDS_PER_CORE - 1)))
-
-#define	CMI_HDL_ARR_IDX(coreid, strandid) \
-	(CMI_HDL_ARR_IDX_CORE(coreid) | CMI_HDL_ARR_IDX_STRAND(strandid))
+#define	CMI_MAX_CORES_PER_CHIP(cbits)	(1 << (cbits))
+#define	CMI_MAX_COREID(cbits)		((1 << (cbits)) - 1)
+#define	CMI_MAX_STRANDS_PER_CORE(sbits)	(1 << (sbits))
+#define	CMI_MAX_STRANDID(sbits)		((1 << (sbits)) - 1)
+#define	CMI_MAX_STRANDS_PER_CHIP(cbits, sbits)	\
+	(CMI_MAX_CORES_PER_CHIP(cbits) * CMI_MAX_STRANDS_PER_CORE(sbits))
 
 #define	CMI_CHIPID_ARR_SZ		(1 << CMI_MAX_CHIPID_NBITS)
 
 struct cmih_walk_state {
 	int chipid, coreid, strandid;	/* currently visited cpu */
 	cmi_hdl_ent_t *chip_tab[CMI_CHIPID_ARR_SZ];
+	uint_t core_nbits;
+	uint_t strand_nbits;
 };
 
 /*
@@ -116,22 +107,22 @@
 	uint_t carry = 0;
 
 	/* Check for end of the table */
-	if (wsp->chipid == CMI_MAX_CHIPID &&
-	    wsp->coreid == (CMI_MAX_CORES_PER_CHIP - 1) &&
-	    wsp->strandid == (CMI_MAX_STRANDS_PER_CORE - 1))
+	if (wsp->chipid >= CMI_MAX_CHIPID &&
+	    wsp->coreid >= CMI_MAX_COREID(wsp->core_nbits) &&
+	    wsp->strandid >= CMI_MAX_STRANDID(wsp->strand_nbits))
 		return (B_FALSE);
 
 	/* increment the strand id */
 	wsp->strandid++;
-	carry =  wsp->strandid >> CMI_MAX_STRANDS_PER_CORE_NBITS;
-	wsp->strandid =  wsp->strandid & (CMI_MAX_STRANDS_PER_CORE - 1);
+	carry =  wsp->strandid >> wsp->strand_nbits;
+	wsp->strandid =  wsp->strandid & CMI_MAX_STRANDID(wsp->strand_nbits);
 	if (carry == 0)
 		return (B_TRUE);
 
 	/* increment the core id */
 	wsp->coreid++;
-	carry = wsp->coreid >> CMI_MAX_CORES_PER_CHIP_NBITS;
-	wsp->coreid = wsp->coreid & (CMI_MAX_CORES_PER_CHIP - 1);
+	carry = wsp->coreid >> wsp->core_nbits;
+	wsp->coreid = wsp->coreid & CMI_MAX_COREID(wsp->core_nbits);
 	if (carry == 0)
 		return (B_TRUE);
 
@@ -142,7 +133,7 @@
 }
 
 /*
- * Lookup for the hdl entry of a given <chip,core,strand>
+ * Lookup for the hdl entry of a given <chip,core,strand> tuple
  */
 static cmi_hdl_ent_t *
 cmih_ent_lookup(struct cmih_walk_state *wsp)
@@ -151,7 +142,9 @@
 		return (NULL);	/* chip is not present */
 
 	return (wsp->chip_tab[wsp->chipid] +
-	    CMI_HDL_ARR_IDX(wsp->coreid, wsp->strandid));
+	    (((wsp->coreid & CMI_MAX_COREID(wsp->core_nbits)) <<
+	    wsp->strand_nbits) |
+	    ((wsp->strandid) & CMI_MAX_STRANDID(wsp->strand_nbits))));
 }
 
 /* forward decls */
@@ -175,6 +168,20 @@
 	wsp->walk_data = awsp =
 	    mdb_zalloc(sizeof (struct cmih_walk_state), UM_SLEEP);
 
+	/* read the number of core bits and strand bits */
+	if (mdb_readvar(&awsp->core_nbits, "cmi_core_nbits") == -1) {
+		mdb_warn("read of cmi_core_nbits failed");
+		mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
+		wsp->walk_data = NULL;
+		return (WALK_ERR);
+	}
+	if (mdb_readvar(&awsp->strand_nbits, "cmi_strand_nbits") == -1) {
+		mdb_warn("read of cmi_strand_nbits failed");
+		mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
+		wsp->walk_data = NULL;
+		return (WALK_ERR);
+	}
+
 	/* table of chipid entries */
 	if ((sz = mdb_readvar(&awsp->chip_tab, "cmi_chip_tab")) == -1) {
 		mdb_warn("read of cmi_chip_tab failed");
@@ -190,7 +197,8 @@
 	}
 
 	/* read the per-chip table that contains all strands of the chip */
-	sz = CMI_MAX_STRANDS_PER_CHIP * sizeof (cmi_hdl_ent_t);
+	sz = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits, awsp->strand_nbits) *
+	    sizeof (cmi_hdl_ent_t);
 	for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
 		if (awsp->chip_tab[i] == NULL)
 			continue; /* this chip(i) is not present */
@@ -246,12 +254,13 @@
 
 	if (awsp != NULL) {
 		int i;
+		int max_strands = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits,
+		    awsp->strand_nbits);
 		for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
 			/* free the per-chip table */
 			if (awsp->chip_tab[i] != NULL) {
 				mdb_free((void *)awsp->chip_tab[i],
-				    CMI_MAX_STRANDS_PER_CHIP *
-				    sizeof (cmi_hdl_ent_t));
+				    max_strands * sizeof (cmi_hdl_ent_t));
 				awsp->chip_tab[i] = NULL;
 			}
 		}
--- a/usr/src/uts/i86pc/os/cmi_hw.c	Mon Apr 26 15:44:36 2010 -0700
+++ b/usr/src/uts/i86pc/os/cmi_hw.c	Mon Apr 26 16:32:21 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Copyright (c) 2010, Intel Corporation.
@@ -178,25 +177,12 @@
 #define	CMI_MAX_STRANDS_PER_CORE_NBITS	3	/* 8 strands per core max */
 
 #define	CMI_MAX_CHIPID			((1 << (CMI_MAX_CHIPID_NBITS)) - 1)
-#define	CMI_MAX_CORES_PER_CHIP		(1 << CMI_MAX_CORES_PER_CHIP_NBITS)
-#define	CMI_MAX_STRANDS_PER_CORE	(1 << CMI_MAX_STRANDS_PER_CORE_NBITS)
-#define	CMI_MAX_STRANDS_PER_CHIP	(CMI_MAX_CORES_PER_CHIP * \
-					    CMI_MAX_STRANDS_PER_CORE)
-
-/*
- * Handle array indexing within a per-chip table
- *	[6:3] = Core in package,
- *	[2:0] = Strand in core,
- */
-#define	CMI_HDL_ARR_IDX_CORE(coreid) \
-	(((coreid) & (CMI_MAX_CORES_PER_CHIP - 1)) << \
-	CMI_MAX_STRANDS_PER_CORE_NBITS)
-
-#define	CMI_HDL_ARR_IDX_STRAND(strandid) \
-	(((strandid) & (CMI_MAX_STRANDS_PER_CORE - 1)))
-
-#define	CMI_HDL_ARR_IDX(coreid, strandid) \
-	(CMI_HDL_ARR_IDX_CORE(coreid) | CMI_HDL_ARR_IDX_STRAND(strandid))
+#define	CMI_MAX_CORES_PER_CHIP(cbits)	(1 << (cbits))
+#define	CMI_MAX_COREID(cbits)		((1 << (cbits)) - 1)
+#define	CMI_MAX_STRANDS_PER_CORE(sbits)	(1 << (sbits))
+#define	CMI_MAX_STRANDID(sbits)		((1 << (sbits)) - 1)
+#define	CMI_MAX_STRANDS_PER_CHIP(cbits, sbits)	\
+	(CMI_MAX_CORES_PER_CHIP(cbits) * CMI_MAX_STRANDS_PER_CORE(sbits))
 
 #define	CMI_CHIPID_ARR_SZ		(1 << CMI_MAX_CHIPID_NBITS)
 
@@ -208,6 +194,13 @@
 static cmi_hdl_ent_t *cmi_chip_tab[CMI_CHIPID_ARR_SZ];
 
 /*
+ * Default values for the number of core and strand bits.
+ */
+uint_t cmi_core_nbits = CMI_MAX_CORES_PER_CHIP_NBITS;
+uint_t cmi_strand_nbits = CMI_MAX_STRANDS_PER_CORE_NBITS;
+static int cmi_ext_topo_check = 0;
+
+/*
  * Controls where we will source PCI config space data.
  */
 #define	CMI_PCICFG_FLAG_RD_HWOK		0x0001
@@ -1205,6 +1198,9 @@
 static cmi_hdl_ent_t *
 cmi_hdl_ent_lookup(uint_t chipid, uint_t coreid, uint_t strandid)
 {
+	int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
+	    cmi_strand_nbits);
+
 	/*
 	 * Allocate per-chip table which contains a list of handle of
 	 * all strands of the chip.
@@ -1213,17 +1209,21 @@
 		size_t sz;
 		cmi_hdl_ent_t *pg;
 
-		sz = CMI_MAX_STRANDS_PER_CHIP * sizeof (cmi_hdl_ent_t);
+		sz = max_strands * sizeof (cmi_hdl_ent_t);
 		pg = kmem_zalloc(sz, KM_SLEEP);
 
 		/* test and set the per-chip table if it is not allocated */
 		if (atomic_cas_ptr(&cmi_chip_tab[chipid], NULL, pg) != NULL)
-			kmem_free(pg, sz); /* someone beat us */
+			kmem_free(pg, sz); /* someone beats us */
 	}
 
-	return (cmi_chip_tab[chipid] + CMI_HDL_ARR_IDX(coreid, strandid));
+	return (cmi_chip_tab[chipid] +
+	    ((((coreid) & CMI_MAX_COREID(cmi_core_nbits)) << cmi_strand_nbits) |
+	    ((strandid) & CMI_MAX_STRANDID(cmi_strand_nbits))));
 }
 
+extern void cpuid_get_ext_topo(uint_t, uint_t *, uint_t *);
+
 cmi_hdl_t
 cmi_hdl_create(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
     uint_t strandid)
@@ -1231,6 +1231,7 @@
 	cmi_hdl_impl_t *hdl;
 	void *priv;
 	cmi_hdl_ent_t *ent;
+	uint_t vendor;
 
 #ifdef __xpv
 	ASSERT(class == CMI_HDL_SOLARIS_xVM_MCA);
@@ -1238,12 +1239,28 @@
 	ASSERT(class == CMI_HDL_NATIVE);
 #endif
 
-	if (chipid > CMI_MAX_CHIPID ||
-	    coreid > CMI_MAX_CORES_PER_CHIP - 1 ||
-	    strandid > CMI_MAX_STRANDS_PER_CORE - 1)
+	if ((priv = cpu_search(class, chipid, coreid, strandid)) == NULL)
 		return (NULL);
 
-	if ((priv = cpu_search(class, chipid, coreid, strandid)) == NULL)
+	/*
+	 * Assume all chips in the system are the same type.
+	 * For Intel, attempt to check if extended topology is available
+	 * CPUID.EAX=0xB. If so, get the number of core and strand bits.
+	 */
+#ifdef __xpv
+	vendor = _cpuid_vendorstr_to_vendorcode(
+	    (char *)xen_physcpu_vendorstr((xen_mc_lcpu_cookie_t)priv));
+#else
+	vendor = cpuid_getvendor((cpu_t *)priv);
+#endif
+	if (vendor == X86_VENDOR_Intel && cmi_ext_topo_check == 0) {
+		cpuid_get_ext_topo(vendor, &cmi_core_nbits, &cmi_strand_nbits);
+		cmi_ext_topo_check = 1;
+	}
+
+	if (chipid > CMI_MAX_CHIPID ||
+	    coreid > CMI_MAX_COREID(cmi_core_nbits) ||
+	    strandid > CMI_MAX_STRANDID(cmi_strand_nbits))
 		return (NULL);
 
 	hdl = kmem_zalloc(sizeof (*hdl), KM_SLEEP);
@@ -1473,8 +1490,8 @@
 	cmi_hdl_ent_t *ent;
 
 	if (chipid > CMI_MAX_CHIPID ||
-	    coreid > CMI_MAX_CORES_PER_CHIP - 1 ||
-	    strandid > CMI_MAX_STRANDS_PER_CORE - 1)
+	    coreid > CMI_MAX_COREID(cmi_core_nbits) ||
+	    strandid > CMI_MAX_STRANDID(cmi_strand_nbits))
 		return (NULL);
 
 	ent = cmi_hdl_ent_lookup(chipid, coreid, strandid);
@@ -1502,11 +1519,13 @@
 {
 	int i, j;
 	cmi_hdl_ent_t *ent;
+	int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
+	    cmi_strand_nbits);
 
 	for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
 		if (cmi_chip_tab[i] == NULL)
 			continue;
-		for (j = 0, ent = cmi_chip_tab[i]; j < CMI_MAX_STRANDS_PER_CHIP;
+		for (j = 0, ent = cmi_chip_tab[i]; j < max_strands;
 		    j++, ent++) {
 			if (cmi_hdl_canref(ent))
 				return ((cmi_hdl_t)ent->cmae_hdlp);
@@ -1522,11 +1541,13 @@
 {
 	int i, j;
 	cmi_hdl_ent_t *ent;
+	int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
+	    cmi_strand_nbits);
 
 	for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
 		if (cmi_chip_tab[i] == NULL)
 			continue;
-		for (j = 0, ent = cmi_chip_tab[i]; j < CMI_MAX_STRANDS_PER_CHIP;
+		for (j = 0, ent = cmi_chip_tab[i]; j < max_strands;
 		    j++, ent++) {
 			if (cmi_hdl_canref(ent)) {
 				cmi_hdl_impl_t *hdl = ent->cmae_hdlp;
--- a/usr/src/uts/i86pc/os/cpuid.c	Mon Apr 26 15:44:36 2010 -0700
+++ b/usr/src/uts/i86pc/os/cpuid.c	Mon Apr 26 16:32:21 2010 -0700
@@ -4214,3 +4214,69 @@
 	}
 }
 #endif  /* __amd64 && !__xpv */
+
+/*
+ * This function finds the number of bits to represent the number of cores per
+ * chip and the number of strands per core for the Intel platforms.
+ * It re-uses the x2APIC cpuid code of the cpuid_pass2().
+ */
+void
+cpuid_get_ext_topo(uint_t vendor, uint_t *core_nbits, uint_t *strand_nbits)
+{
+	struct cpuid_regs regs;
+	struct cpuid_regs *cp = &regs;
+
+	if (vendor != X86_VENDOR_Intel) {
+		return;
+	}
+
+	/* if the cpuid level is 0xB, extended topo is available. */
+	cp->cp_eax = 0;
+	if (__cpuid_insn(cp) >= 0xB) {
+
+		cp->cp_eax = 0xB;
+		cp->cp_edx = cp->cp_ebx = cp->cp_ecx = 0;
+		(void) __cpuid_insn(cp);
+
+		/*
+		 * Check CPUID.EAX=0BH, ECX=0H:EBX is non-zero, which
+		 * indicates that the extended topology enumeration leaf is
+		 * available.
+		 */
+		if (cp->cp_ebx) {
+			uint_t coreid_shift = 0;
+			uint_t chipid_shift = 0;
+			uint_t i;
+			uint_t level;
+
+			for (i = 0; i < CPI_FNB_ECX_MAX; i++) {
+				cp->cp_eax = 0xB;
+				cp->cp_ecx = i;
+
+				(void) __cpuid_insn(cp);
+				level = CPI_CPU_LEVEL_TYPE(cp);
+
+				if (level == 1) {
+					/*
+					 * Thread level processor topology
+					 * Number of bits shift right APIC ID
+					 * to get the coreid.
+					 */
+					coreid_shift = BITX(cp->cp_eax, 4, 0);
+				} else if (level == 2) {
+					/*
+					 * Core level processor topology
+					 * Number of bits shift right APIC ID
+					 * to get the chipid.
+					 */
+					chipid_shift = BITX(cp->cp_eax, 4, 0);
+				}
+			}
+
+			if (coreid_shift > 0 && chipid_shift > coreid_shift) {
+				*strand_nbits = coreid_shift;
+				*core_nbits = chipid_shift - coreid_shift;
+			}
+		}
+	}
+}