Mercurial > illumos > illumos-gate
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 = ®s; + + 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; + } + } + } +}