Mercurial > illumos > illumos-gate
changeset 10947:2ecbb0a4d189
6843035 Need support for Magny-Cours processors
6860401 FMA CPU Topology & Memory Topology needs to support Magny Cours(Multi chip Module)
Portions contributed by Boris.Ostrovsky@amd.com and Hans.Rosenfeld@amd.com
author | Srihari Venkatesan <Srihari.Venkatesan@Sun.COM> |
---|---|
date | Wed, 04 Nov 2009 01:45:19 -0800 |
parents | 324bab2b3370 |
children | c686aa11575c |
files | usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c usr/src/lib/fm/topo/modules/i86pc/chip/chip.c usr/src/lib/fm/topo/modules/i86pc/chip/chip.h usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c usr/src/uts/common/disp/cmt.c usr/src/uts/common/sys/devfm.h usr/src/uts/common/sys/pghw.h usr/src/uts/i86pc/cpu/amd_opteron/ao.h usr/src/uts/i86pc/cpu/amd_opteron/ao_cpu.c usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c usr/src/uts/i86pc/cpu/authenticamd/authamd.h usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c usr/src/uts/i86pc/os/cmi_hw.c usr/src/uts/i86pc/os/cpuid.c usr/src/uts/i86pc/os/lgrpplat.c usr/src/uts/i86pc/os/mp_machdep.c usr/src/uts/intel/io/devfm_machdep.c usr/src/uts/intel/sys/cpu_module.h usr/src/uts/intel/sys/x86_archext.h |
diffstat | 19 files changed, 504 insertions(+), 264 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c Wed Nov 04 01:45:19 2009 -0800 @@ -33,9 +33,11 @@ enum cmi_hdl_class cmih_class; /* Handle nature */ struct cmi_hdl_ops *cmih_ops; /* Operations vector */ uint_t cmih_chipid; /* Chipid of cpu resource */ + uint_t cmih_procnodeid; /* Nodeid of cpu resource */ uint_t cmih_coreid; /* Core within die */ uint_t cmih_strandid; /* Thread within core */ boolean_t cmih_mstrand; /* cores are multithreaded */ + uint_t cmih_procnodes_per_pkg; /* Nodes in a processor */ volatile uint32_t *cmih_refcntp; /* Reference count pointer */ uint64_t cmih_msrsrc; /* MSR data source flags */ void *cmih_hdlpriv; /* cmi_hw.c private data */
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c Wed Nov 04 01:45:19 2009 -0800 @@ -278,7 +278,8 @@ (void) topo_pgroup_create(strand, &strand_pgroup, &err); nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL, - STRAND_CHIP_ID, STRAND_CORE_ID, STRAND_CPU_ID, NULL); + STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID, + NULL); if (FM_AWARE_SMBIOS(mod)) { (void) topo_node_label_set(strand, NULL, &perr); @@ -381,8 +382,8 @@ "topo_method_register failed\n"); (void) topo_pgroup_create(core, &core_pgroup, &err); - nerr -= add_nvlist_longprop(mod, core, cpu, PGNAME(CORE), - CORE_CHIP_ID, NULL); + nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL, + CORE_CHIP_ID, CORE_PROCNODE_ID, NULL); if (topo_node_range_create(mod, core, STRAND_NODE_NAME, 0, 255) != 0) @@ -456,11 +457,11 @@ int mc_offchip) { tnode_t *chip; - int32_t chipid; nvlist_t *fmri = NULL; int err, perr, nerr = 0; - int32_t fms[3]; + int32_t chipid, procnodeid, procnodes_per_pkg; const char *vendor; + int32_t family, model; boolean_t create_mc = B_FALSE; uint16_t smbios_id; @@ -468,9 +469,17 @@ * /dev/fm will export the chipid based on SMBIOS' ordering * of Type-4 structures, if SMBIOS meets FMA needs */ - if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CHIP_ID, &chipid)) - != 0) { - whinge(mod, &nerr, "create_chip: lookup chip_id failed: %s\n", + err = nvlist_lookup_pairs(cpu, 0, + FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32, &chipid, + FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32, &procnodes_per_pkg, + FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32, &procnodeid, + FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING, &vendor, + FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32, &family, + FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32, &model, + NULL); + + if (err) { + whinge(mod, NULL, "create_chip: lookup failed: %s\n", strerror(err)); return (-1); } @@ -513,9 +522,9 @@ (void) topo_pgroup_create(chip, &chip_pgroup, &err); nerr -= add_nvlist_strprop(mod, chip, cpu, PGNAME(CHIP), - CHIP_VENDOR_ID, &vendor); + CHIP_VENDOR_ID, NULL); nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP), - fms, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL); + NULL, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL); if (FM_AWARE_SMBIOS(mod)) { int fru = 0; @@ -598,10 +607,15 @@ whinge(mod, &nerr, "create_chip: " "topo_method_register failed\n"); - if (topo_node_range_create(mod, chip, CORE_NODE_NAME, - 0, 255) != 0) + if (topo_node_range_create(mod, chip, CORE_NODE_NAME, 0, 255)) return (-1); + if (strcmp(vendor, "AuthenticAMD") == 0) { + if (topo_node_range_create(mod, chip, MCT_NODE_NAME, + 0, 255)) + return (-1); + } + create_mc = B_TRUE; } @@ -637,15 +651,11 @@ * If SMBIOS meets FMA needs, when Multi-Chip-Module is * addressed, mc instances should be derived from SMBIOS */ - if (create_mc) { - if (strcmp(vendor, "AuthenticAMD") == 0) - amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth, - fms[0], fms[1], fms[2], &nerr); - else if (!mc_offchip) { - onchip_mc_create(mod, smbios_id, chip, - MCT_NODE_NAME, auth); - } - } + if (strcmp(vendor, "AuthenticAMD") == 0) { + amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth, + procnodeid, procnodes_per_pkg, family, model, &nerr); + } else if (create_mc && !mc_offchip) + onchip_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth); return (err == 0 && nerr == 0 ? 0 : -1); }
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h Wed Nov 04 01:45:19 2009 -0800 @@ -52,6 +52,10 @@ (*(int *)topo_mod_getspecific(mod) == X86PI_FULL)) #define IGNORE_ID 0xFFFF +/* + * These definitions are for the Tree Nodes + * in the FM Topology + */ #define CHIP_NODE_NAME "chip" #define CORE_NODE_NAME "core" #define STRAND_NODE_NAME "strand" @@ -73,14 +77,23 @@ #define CHIP_NCORE "ncore_per_chip" /* + * memory-controller-properties + * check usr/src/uts/i86pc/os/cpuid.c to understand more + * on procnodeid values for AMD & Intel + */ +#define MCT_PROCNODE_ID "procnodeid" + +/* * core-properties */ #define CORE_CHIP_ID "chip_id" +#define CORE_PROCNODE_ID "procnodeid" /* * strand-properties */ #define STRAND_CHIP_ID "chip_id" +#define STRAND_PROCNODE_ID "procnodeid" #define STRAND_CORE_ID "core_id" #define STRAND_PKG_CORE_ID "pkg_core_id" #define STRAND_CPU_ID "cpuid" @@ -176,8 +189,8 @@ /* * Prototypes for chip_amd.c */ -extern void amd_mc_create(topo_mod_t *, uint16_t, tnode_t *, - const char *, nvlist_t *, int, int, int, int *); +extern void amd_mc_create(topo_mod_t *, uint16_t, tnode_t *, const char *, + nvlist_t *, int32_t, int32_t, int, int, int *); /* * Prototypes for chip_intel.c
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c Wed Nov 04 01:45:19 2009 -0800 @@ -133,26 +133,23 @@ * We create a tree of dram-channel and chip-select nodes below the * memory-controller node. There will be two dram channels and 8 chip-selects * below each, regardless of actual socket type, processor revision and so on. - * This is adequate for generic diagnosis up to family 0x10 revision C. - * When support for revision D is implemented (or maybe C) we should take - * the opportunity to rework the topology tree completely (socket change will - * mean there can be no diagnosis history tied to the topology). + * This is adequate for generic diagnosis up to family 0x10 revision D. */ /*ARGSUSED*/ static int amd_generic_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *cnode, - tnode_t *mcnode, int family, int model, int stepping, nvlist_t *auth) + tnode_t *mcnode, int family, int model, nvlist_t *auth) { int chan, cs; /* * Elsewhere we have already returned for families less than 0xf. * This "generic" topology is adequate for all of family 0xf and - * for revisions A, B and C of family 0x10 (for the list of models + * for revisions A to D of family 0x10 (for the list of models * in each revision, refer to usr/src/uts/i86pc/os/cpuid_subr.c). - * We cover all family 0x10 models, till model 8. + * We cover all family 0x10 models, till model 9. */ - if (family > 0x10 || (family == 0x10 && model > 8)) + if (family > 0x10 || (family == 0x10 && model > 9)) return (1); if (topo_node_range_create(mod, mcnode, CHAN_NODE_NAME, 0, @@ -719,54 +716,53 @@ } void -amd_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *pnode, const char *name, - nvlist_t *auth, int family, int model, int stepping, int *nerrp) +amd_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *pnode, + const char *name, nvlist_t *auth, int32_t procnodeid, + int32_t procnodes_per_pkg, int family, + int model, int *nerrp) { tnode_t *mcnode; nvlist_t *fmri; nvpair_t *nvp; nvlist_t *mc = NULL; int i, err; + int mcnum = procnodeid % procnodes_per_pkg; char *serial = NULL; char *part = NULL; char *rev = NULL; /* * Return with no error for anything before AMD family 0xf - we - * won't generate even a generic memory topolofy for earlier + * won't generate even a generic memory topology for earlier * families. */ if (family < 0xf) return; + if (topo_node_lookup(pnode, name, mcnum) != NULL) + return; + if (FM_AWARE_SMBIOS(mod)) { (void) topo_node_resource(pnode, &fmri, &err); (void) nvlist_lookup_string(fmri, "serial", &serial); (void) nvlist_lookup_string(fmri, "part", &part); (void) nvlist_lookup_string(fmri, "revision", &rev); + nvlist_free(fmri); } - if (mkrsrc(mod, pnode, name, 0, auth, &fmri) != 0) { + if (mkrsrc(mod, pnode, name, mcnum, auth, &fmri) != 0) { whinge(mod, nerrp, "mc_create: mkrsrc failed\n"); return; } - if (topo_node_range_create(mod, pnode, name, 0, 0) < 0) { - nvlist_free(fmri); - whinge(mod, nerrp, "mc_create: node range create failed\n"); - return; - } - if (FM_AWARE_SMBIOS(mod)) { (void) nvlist_add_string(fmri, "serial", serial); (void) nvlist_add_string(fmri, "part", part); (void) nvlist_add_string(fmri, "revision", rev); } - if ((mcnode = topo_node_bind(mod, pnode, name, 0, + if ((mcnode = topo_node_bind(mod, pnode, name, mcnum, fmri)) == NULL) { - nvlist_free(mc); - topo_node_range_destroy(pnode, name); nvlist_free(fmri); whinge(mod, nerrp, "mc_create: mc bind failed\n"); return; @@ -781,6 +777,14 @@ nvlist_free(fmri); + if (topo_pgroup_create(mcnode, &mc_pgroup, &err) < 0) + whinge(mod, nerrp, "mc_create: topo_pgroup_create failed\n"); + + if (topo_prop_set_int32(mcnode, PGNAME(MCT), MCT_PROCNODE_ID, + TOPO_PROP_IMMUTABLE, procnodeid, nerrp) != 0) + whinge(mod, nerrp, "mc_create: topo_prop_set_int32 failed to" + "add node id\n"); + if ((mc = amd_lookup_by_mcid(mod, topo_node_instance(pnode))) == NULL) { /* * If a memory-controller driver exists for this chip model @@ -790,7 +794,7 @@ * creating a generic maximal topology. */ if (amd_generic_mc_create(mod, smbid, pnode, mcnode, - family, model, stepping, auth) != 0) + family, model, auth) != 0) whinge(mod, nerrp, "mc_create: amd_generic_mc_create failed\n"); return; @@ -799,9 +803,6 @@ /* * Add memory controller properties */ - if (topo_pgroup_create(mcnode, &mc_pgroup, &err) < 0) - whinge(mod, nerrp, "mc_create: topo_pgroup_create failed\n"); - for (nvp = nvlist_next_nvpair(mc, NULL); nvp != NULL; nvp = nvlist_next_nvpair(mc, nvp)) { char *name = nvpair_name(nvp);
--- a/usr/src/uts/common/disp/cmt.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/common/disp/cmt.c Wed Nov 04 01:45:19 2009 -0800 @@ -253,6 +253,7 @@ switch (hw) { case PGHW_IPIPE: case PGHW_FPU: + case PGHW_PROCNODE: case PGHW_CHIP: return (CMT_BALANCE); case PGHW_CACHE: @@ -1122,7 +1123,8 @@ static void pg_cmt_hier_sort(pg_cmt_t **hier, int size) { - int i, j, inc; + int i, j, inc, sz; + int start, end; pg_t *tmp; pg_t **h = (pg_t **)hier; @@ -1151,12 +1153,29 @@ * Break ties by asking the platform. * Determine if h[i] outranks h[i + 1] and if so, swap them. */ - for (i = 0; i < size - 1; i++) { - if ((PG_NUM_CPUS(h[i]) == PG_NUM_CPUS(h[i + 1])) && - pg_cmt_hier_rank(hier[i], hier[i + 1]) == hier[i]) { + for (start = 0; start < size; start++) { + + /* + * Find various contiguous sets of elements, + * in the array, with the same number of cpus + */ + end = start; + sz = PG_NUM_CPUS(h[start]); + while ((end < size) && (sz == PG_NUM_CPUS(h[end]))) + end++; + /* + * Sort each such set of the array by rank + */ + for (i = start + 1; i < end; i++) { + j = i - 1; tmp = h[i]; - h[i] = h[i + 1]; - h[i + 1] = tmp; + while (j >= start && + pg_cmt_hier_rank(hier[j], + (pg_cmt_t *)tmp) == hier[j]) { + h[j + 1] = h[j]; + j--; + } + h[j + 1] = tmp; } } }
--- a/usr/src/uts/common/sys/devfm.h Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/common/sys/devfm.h Wed Nov 04 01:45:19 2009 -0800 @@ -83,13 +83,15 @@ /* * Constants */ -#define FM_PAGE_RETIRE_FMRI "fmri" -#define FM_PHYSCPU_INFO_CPUS "cpus" -#define FM_CPU_RETIRE_CHIP_ID "chip_id" -#define FM_CPU_RETIRE_CORE_ID "core_id" -#define FM_CPU_RETIRE_STRAND_ID "strand_id" -#define FM_CPU_RETIRE_OLDSTATUS "oldstatus" -#define FM_GENTOPO_LEGACY "gentopolegacy" +#define FM_PAGE_RETIRE_FMRI "fmri" +#define FM_PHYSCPU_INFO_CPUS "cpus" +#define FM_CPU_RETIRE_CHIP_ID "chip_id" +#define FM_PHYSCPU_INFO_NPROCNODES "procnodes_per_pkg" +#define FM_PHYSCPU_INFO_PROCNODE_ID "procnodeid" +#define FM_CPU_RETIRE_CORE_ID "core_id" +#define FM_CPU_RETIRE_STRAND_ID "strand_id" +#define FM_CPU_RETIRE_OLDSTATUS "oldstatus" +#define FM_GENTOPO_LEGACY "gentopolegacy" /* * Properties set by FM_PHYSCPU_INFO
--- a/usr/src/uts/common/sys/pghw.h Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/common/sys/pghw.h Wed Nov 04 01:45:19 2009 -0800 @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -57,6 +58,15 @@ } pghw_type_t; /* + * See comments in usr/src/uts/i86pc/os/cpuid.c + * for description of processor nodes + * + * From sharing point of view processor nodes are + * very similar to memory pipes, hence the #define below. + */ +#define PGHW_PROCNODE PGHW_MPIPE + +/* * Returns true if the hardware is a type of power management domain */ #define PGHW_IS_PM_DOMAIN(hw) \
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao.h Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao.h Wed Nov 04 01:45:19 2009 -0800 @@ -20,15 +20,13 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _AO_H #define _AO_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/mc.h> #include <sys/mca_amd.h> @@ -189,7 +187,7 @@ /* * Local functions */ -extern void ao_chip_scrubber_enable(cmi_hdl_t, ao_ms_data_t *); +extern void ao_procnode_scrubber_enable(cmi_hdl_t, ao_ms_data_t *); extern void ao_pcicfg_write(uint_t, uint_t, uint_t, uint32_t); extern uint32_t ao_pcicfg_read(uint_t, uint_t, uint_t); extern void ao_bankstatus_prewrite(cmi_hdl_t, ao_ms_data_t *);
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_cpu.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_cpu.c Wed Nov 04 01:45:19 2009 -0800 @@ -20,12 +20,10 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/pghw.h> #include <sys/cmn_err.h> @@ -61,23 +59,23 @@ } ao_scrub_policy = AO_SCRUB_MAX; void -ao_pcicfg_write(uint_t chipid, uint_t func, uint_t reg, uint32_t val) +ao_pcicfg_write(uint_t procnodeid, uint_t func, uint_t reg, uint32_t val) { - ASSERT(chipid + 24 <= 31); + ASSERT(procnodeid + 24 <= 31); ASSERT((func & 7) == func); ASSERT((reg & 3) == 0 && reg < 256); - cmi_pci_putl(0, chipid + 24, func, reg, 0, val); + cmi_pci_putl(0, procnodeid + 24, func, reg, 0, val); } uint32_t -ao_pcicfg_read(uint_t chipid, uint_t func, uint_t reg) +ao_pcicfg_read(uint_t procnodeid, uint_t func, uint_t reg) { - ASSERT(chipid + 24 <= 31); + ASSERT(procnodeid + 24 <= 31); ASSERT((func & 7) == func); ASSERT((reg & 3) == 0 && reg < 256); - return (cmi_pci_getl(0, chipid + 24, func, reg, 0, 0)); + return (cmi_pci_getl(0, procnodeid + 24, func, reg, 0, 0)); } @@ -97,17 +95,17 @@ } /* - * Enable the chip-specific hardware scrubbers for the D$ and L2$. We set + * Enable the node-specific hardware scrubbers for the D$ and L2$. We set * the scrubber rate based on a set of tunables defined at the top of the file. */ void -ao_chip_scrubber_enable(cmi_hdl_t hdl, ao_ms_data_t *ao) +ao_procnode_scrubber_enable(cmi_hdl_t hdl, ao_ms_data_t *ao) { - chipid_t chipid = cmi_hdl_chipid(hdl); + uint_t procnodeid = cmi_hdl_procnodeid(hdl); union mcreg_scrubctl scrubctl; ao->ao_ms_shared->aos_bcfg_scrubctl = MCREG_VAL32(&scrubctl) = - ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL); + ao_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL); if (ao_scrub_policy == AO_SCRUB_BIOSDEFAULT) return; @@ -148,6 +146,6 @@ MCREG_FIELD_CMN(&scrubctl, DcacheScrub) = ao_scrub_rate_dcache; MCREG_FIELD_CMN(&scrubctl, L2Scrub) = ao_scrub_rate_l2cache; - ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL, + ao_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL, MCREG_VAL32(&scrubctl)); }
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c Wed Nov 04 01:45:19 2009 -0800 @@ -405,7 +405,7 @@ ao_nb_cfg(ao_ms_data_t *ao, uint32_t rev) { const struct ao_nb_cfg *nbcp = &ao_cfg_extra[0]; - uint_t chipid = pg_plat_hw_instance_id(CPU, PGHW_CHIP); + uint_t procnodeid = pg_plat_hw_instance_id(CPU, PGHW_PROCNODE); uint32_t val; /* @@ -416,7 +416,7 @@ * memory errors. */ ao->ao_ms_shared->aos_bcfg_nb_cfg = val = - ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG); + ao_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG); switch (ao_nb_watchdog_policy) { case AO_NB_WDOG_LEAVEALONE: @@ -461,26 +461,25 @@ nbcp++; } - ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG, val); + ao_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG, val); } static void ao_dram_cfg(ao_ms_data_t *ao, uint32_t rev) { - uint_t chipid = pg_plat_hw_instance_id(CPU, PGHW_CHIP); + uint_t procnodeid = pg_plat_hw_instance_id(CPU, PGHW_PROCNODE); union mcreg_dramcfg_lo dcfglo; ao->ao_ms_shared->aos_bcfg_dcfg_lo = MCREG_VAL32(&dcfglo) = - ao_pcicfg_read(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGLO); + ao_pcicfg_read(procnodeid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGLO); ao->ao_ms_shared->aos_bcfg_dcfg_hi = - ao_pcicfg_read(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGHI); - + ao_pcicfg_read(procnodeid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGHI); #ifdef OPTERON_ERRATUM_172 if (X86_CHIPREV_MATCH(rev, AO_F_REVS_FG) && MCREG_FIELD_F_revFG(&dcfglo, ParEn)) { MCREG_FIELD_F_revFG(&dcfglo, ParEn) = 0; - ao_pcicfg_write(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGLO, - MCREG_VAL32(&dcfglo)); + ao_pcicfg_write(procnodeid, MC_FUNC_DRAMCTL, + MC_DC_REG_DRAMCFGLO, MCREG_VAL32(&dcfglo)); } #endif } @@ -501,12 +500,12 @@ static void ao_sparectl_cfg(ao_ms_data_t *ao) { - uint_t chipid = pg_plat_hw_instance_id(CPU, PGHW_CHIP); + uint_t procnodeid = pg_plat_hw_instance_id(CPU, PGHW_PROCNODE); union mcreg_sparectl sparectl; int chan, cs; ao->ao_ms_shared->aos_bcfg_nb_sparectl = MCREG_VAL32(&sparectl) = - ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL); + ao_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL); if (ao_nb_cfg_sparectl_noseize) return; /* stash BIOS value, but no changes */ @@ -528,7 +527,7 @@ for (cs = 0; cs < MC_CHIP_NCS; cs++) { MCREG_FIELD_F_revFG(&sparectl, EccErrCntDramCs) = cs; - ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, + ao_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL, MCREG_VAL32(&sparectl)); } } @@ -884,7 +883,7 @@ if (ao_chip_once(ao, AO_CFGONCE_DRAMCFG) == B_TRUE) ao_dram_cfg(ao, rev); - ao_chip_scrubber_enable(hdl, ao); + ao_procnode_scrubber_enable(hdl, ao); } /*
--- a/usr/src/uts/i86pc/cpu/authenticamd/authamd.h Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/authenticamd/authamd.h Wed Nov 04 01:45:19 2009 -0800 @@ -20,15 +20,13 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _AUTHAMD_H #define _AUTHAMD_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/mca_amd.h> #include <sys/cpu_module_ms_impl.h> @@ -37,8 +35,8 @@ extern "C" { #endif -#define AUTHAMD_MAX_CHIPS 8 /* max number of chips */ -#define AUTHAMD_DRAM_NCHANNEL 2 /* dram channels per chip */ +#define AUTHAMD_MAX_NODES 8 /* max number of nodes */ +#define AUTHAMD_DRAM_NCHANNEL 2 /* dram channels per node */ #define AUTHAMD_DRAM_NCS 8 /* chip-selects per channel */ #define AUTHAMD_FAMILY_6 0x6 @@ -66,10 +64,11 @@ #pragma pack() /* - * Per chip shared state + * Per node shared state */ -struct authamd_chipshared { +struct authamd_nodeshared { uint_t acs_chipid; + uint_t acs_procnodeid; uint_t acs_family; /* family number */ uint32_t acs_rev; /* revision per cpuid_getchiprev */ volatile ulong_t acs_cfgonce; /* Config performed once per chip */ @@ -91,7 +90,7 @@ struct authamd_data { cmi_hdl_t amd_hdl; /* cpu we're associated with */ uint64_t amd_hwcr; - struct authamd_chipshared *amd_shared; + struct authamd_nodeshared *amd_shared; }; #ifdef _KERNEL
--- a/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c Wed Nov 04 01:45:19 2009 -0800 @@ -209,7 +209,7 @@ }; -static struct authamd_chipshared *authamd_shared[AUTHAMD_MAX_CHIPS]; +static struct authamd_nodeshared *authamd_shared[AUTHAMD_MAX_NODES]; static int authamd_chip_once(authamd_data_t *authamd, enum authamd_cfgonce_bitnum what) @@ -219,23 +219,23 @@ } static void -authamd_pcicfg_write(uint_t chipid, uint_t func, uint_t reg, uint32_t val) +authamd_pcicfg_write(uint_t procnodeid, uint_t func, uint_t reg, uint32_t val) { - ASSERT(chipid + 24 <= 31); + ASSERT(procnodeid + 24 <= 31); ASSERT((func & 7) == func); ASSERT((reg & 3) == 0 && reg < 256); - cmi_pci_putl(0, chipid + 24, func, reg, 0, val); + cmi_pci_putl(0, procnodeid + 24, func, reg, 0, val); } static uint32_t -authamd_pcicfg_read(uint_t chipid, uint_t func, uint_t reg) +authamd_pcicfg_read(uint_t procnodeid, uint_t func, uint_t reg) { - ASSERT(chipid + 24 <= 31); + ASSERT(procnodeid + 24 <= 31); ASSERT((func & 7) == func); ASSERT((reg & 3) == 0 && reg < 256); - return (cmi_pci_getl(0, chipid + 24, func, reg, 0, 0)); + return (cmi_pci_getl(0, procnodeid + 24, func, reg, 0, 0)); } void @@ -283,7 +283,7 @@ authamd_read_ecccnt(authamd_data_t *authamd, struct authamd_logout *msl) { union mcreg_sparectl sparectl; - uint_t chipid = authamd->amd_shared->acs_chipid; + uint_t procnodeid = authamd->amd_shared->acs_procnodeid; uint_t family = authamd->amd_shared->acs_family; uint32_t rev = authamd->amd_shared->acs_rev; int chan, cs; @@ -300,7 +300,8 @@ } MCREG_VAL32(&sparectl) = - authamd_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL); + authamd_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, + MC_CTL_REG_SPARECTL); switch (family) { case AUTHAMD_FAMILY_F: @@ -338,10 +339,10 @@ break; } - authamd_pcicfg_write(chipid, MC_FUNC_MISCCTL, + authamd_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL, MCREG_VAL32(&sparectl)); - MCREG_VAL32(&sparectl) = authamd_pcicfg_read(chipid, + MCREG_VAL32(&sparectl) = authamd_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL); switch (family) { @@ -374,7 +375,7 @@ authamd_clear_ecccnt(authamd_data_t *authamd, boolean_t clrint) { union mcreg_sparectl sparectl; - uint_t chipid = authamd->amd_shared->acs_chipid; + uint_t procnodeid = authamd->amd_shared->acs_procnodeid; uint_t family = authamd->amd_shared->acs_family; uint32_t rev = authamd->amd_shared->acs_rev; int chan, cs; @@ -383,7 +384,8 @@ return; MCREG_VAL32(&sparectl) = - authamd_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL); + authamd_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, + MC_CTL_REG_SPARECTL); switch (family) { case AUTHAMD_FAMILY_F: @@ -403,7 +405,7 @@ break; } - authamd_pcicfg_write(chipid, MC_FUNC_MISCCTL, + authamd_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL, MCREG_VAL32(&sparectl)); for (chan = 0; chan < AUTHAMD_DRAM_NCHANNEL; chan++) { @@ -436,7 +438,7 @@ break; } - authamd_pcicfg_write(chipid, MC_FUNC_MISCCTL, + authamd_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL, MCREG_VAL32(&sparectl)); } } @@ -449,31 +451,18 @@ * 0: unsupported */ static int -authamd_supported(uint_t family, uint32_t rev, uint_t chipid) +authamd_supported(cmi_hdl_t hdl) { - uint32_t nbcap; - - if (family == AUTHAMD_FAMILY_6) - return (1); - - if (family == AUTHAMD_FAMILY_F) - return (1); + uint_t family = cmi_hdl_family(hdl); - /* - * On Family 10h, authamd is currently unsupported when there are - * multiple nodes on a processor chip. - */ - if (X86_CHIPREV_ATLEAST(rev, X86_CHIPREV_AMD_10_REV_D)) { - nbcap = authamd_pcicfg_read(chipid, MC_FUNC_MISCCTL, - MC_CTL_REG_NBCAP); - if ((nbcap & MC_NBCAP_MULTINODECPU) == 0) - return (1); - } else { - if (X86_CHIPREV_ATLEAST(rev, X86_CHIPREV_AMD_10_REV_A)) - return (1); + switch (family) { + case AUTHAMD_FAMILY_6: + case AUTHAMD_FAMILY_F: + case AUTHAMD_FAMILY_10: + return (1); + default: + return (0); } - - return (0); } /* @@ -487,14 +476,15 @@ authamd_init(cmi_hdl_t hdl, void **datap) { uint_t chipid = cmi_hdl_chipid(hdl); - struct authamd_chipshared *sp, *osp; + uint_t procnodeid = cmi_hdl_procnodeid(hdl); + struct authamd_nodeshared *sp, *osp; uint_t family = cmi_hdl_family(hdl); uint32_t rev = cmi_hdl_chiprev(hdl); authamd_data_t *authamd; uint64_t cap; if (authamd_ms_support_disable || - !authamd_supported(family, rev, chipid)) + !authamd_supported(hdl)) return (ENOTSUP); if (!(x86_feature & X86_MCA)) @@ -510,16 +500,17 @@ cmi_hdl_hold(hdl); /* release in fini */ authamd->amd_hdl = hdl; - if ((sp = authamd_shared[chipid]) == NULL) { - sp = kmem_zalloc(sizeof (struct authamd_chipshared), KM_SLEEP); + if ((sp = authamd_shared[procnodeid]) == NULL) { + sp = kmem_zalloc(sizeof (struct authamd_nodeshared), KM_SLEEP); sp->acs_chipid = chipid; + sp->acs_procnodeid = procnodeid; sp->acs_family = family; - sp->acs_rev = cmi_hdl_chiprev(hdl); + sp->acs_rev = rev; membar_producer(); - osp = atomic_cas_ptr(&authamd_shared[chipid], NULL, sp); + osp = atomic_cas_ptr(&authamd_shared[procnodeid], NULL, sp); if (osp != NULL) { - kmem_free(sp, sizeof (struct authamd_chipshared)); + kmem_free(sp, sizeof (struct authamd_nodeshared)); sp = osp; } } @@ -682,7 +673,7 @@ { authamd_data_t *authamd = cms_hdl_getcmsdata(hdl); uint32_t rev = authamd->amd_shared->acs_rev; - uint_t chipid = authamd->amd_shared->acs_chipid; + uint_t procnodeid = authamd->amd_shared->acs_procnodeid; /* * On chips with a NB online spare control register take control @@ -732,7 +723,7 @@ */ if (AUTHAMD_DO_NBMCACFG(rev) && authamd_chip_once(authamd, AUTHAMD_CFGONCE_NBMCACFG)) { - uint32_t val = authamd_pcicfg_read(chipid, MC_FUNC_MISCCTL, + uint32_t val = authamd_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG); switch (authamd_nb_watchdog_policy) { @@ -774,8 +765,8 @@ val &= ~authamd_nb_mcacfg_remove; val |= authamd_nb_mcacfg_add; - authamd_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG, - val); + authamd_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, + MC_CTL_REG_NBCFG, val); } /* @@ -785,13 +776,14 @@ if (AUTHAMD_HAS_CHIPSCRUB(rev) && authamd_scrub_policy != AUTHAMD_SCRUB_BIOSDEFAULT && authamd_chip_once(authamd, AUTHAMD_CFGONCE_CACHESCRUB)) { - uint32_t val = authamd_pcicfg_read(chipid, MC_FUNC_MISCCTL, + uint32_t val = authamd_pcicfg_read(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL); int l3cap = 0; if (AUTHAMD_L3CAPABLE(rev)) { - l3cap = (authamd_pcicfg_read(chipid, MC_FUNC_MISCCTL, - MC_CTL_REG_NBCAP) & MC_NBCAP_L3CAPABLE) != 0; + l3cap = (authamd_pcicfg_read(procnodeid, + MC_FUNC_MISCCTL, MC_CTL_REG_NBCAP) & + MC_NBCAP_L3CAPABLE) != 0; } authamd_scrub_rate_dcache = @@ -813,7 +805,7 @@ authamd_scrub_rate_dcache, authamd_scrub_rate_l2cache, val & AMD_NB_SCRUBCTL_DRAM_MASK); - authamd_pcicfg_write(chipid, MC_FUNC_MISCCTL, + authamd_pcicfg_write(procnodeid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL, val); } @@ -826,7 +818,7 @@ authamd_poll_ownermask(cmi_hdl_t hdl, hrtime_t pintvl) { authamd_data_t *authamd = cms_hdl_getcmsdata(hdl); - struct authamd_chipshared *acsp = authamd->amd_shared; + struct authamd_nodeshared *acsp = authamd->amd_shared; hrtime_t now = gethrtime_waitfree(); hrtime_t last = acsp->acs_poll_timestamp; int dopoll = 0; @@ -985,12 +977,16 @@ authamd_logout_t *msl; nvlist_t *nvl; int nelems = 0; - int i, chan, cs; + int i, chan, cs, mc; nvlist_t *board_list = NULL; if ((msl = mslogout) == NULL) return; + /* Assume all processors have the same number of nodes */ + mc = authamd->amd_shared->acs_procnodeid % + cpuid_get_procnodes_per_pkg(CPU); + for (chan = 0; chan < AUTHAMD_DRAM_NCHANNEL; chan++) { for (cs = 0; cs < AUTHAMD_DRAM_NCS; cs++) { if (msl->aal_eccerrcnt[chan][cs] == 0) @@ -1017,7 +1013,7 @@ NULL, NULL, 5, "motherboard", 0, "chip", authamd->amd_shared->acs_chipid, - "memory-controller", 0, + "memory-controller", mc, "dram-channel", chan, "chip-select", cs); }
--- a/usr/src/uts/i86pc/os/cmi_hw.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/os/cmi_hw.c Wed Nov 04 01:45:19 2009 -0800 @@ -70,8 +70,10 @@ enum cmi_hdl_class cmih_class; /* Handle nature */ const struct cmi_hdl_ops *cmih_ops; /* Operations vector */ uint_t cmih_chipid; /* Chipid of cpu resource */ + uint_t cmih_procnodeid; /* Nodeid of cpu resource */ uint_t cmih_coreid; /* Core within die */ uint_t cmih_strandid; /* Thread within core */ + uint_t cmih_procnodes_per_pkg; /* Nodes in a processor */ boolean_t cmih_mstrand; /* cores are multithreaded */ volatile uint32_t *cmih_refcntp; /* Reference count pointer */ uint64_t cmih_msrsrc; /* MSR data source flags */ @@ -105,8 +107,10 @@ uint_t (*cmio_model)(cmi_hdl_impl_t *); uint_t (*cmio_stepping)(cmi_hdl_impl_t *); uint_t (*cmio_chipid)(cmi_hdl_impl_t *); + uint_t (*cmio_procnodeid)(cmi_hdl_impl_t *); uint_t (*cmio_coreid)(cmi_hdl_impl_t *); uint_t (*cmio_strandid)(cmi_hdl_impl_t *); + uint_t (*cmio_procnodes_per_pkg)(cmi_hdl_impl_t *); uint_t (*cmio_strand_apicid)(cmi_hdl_impl_t *); uint32_t (*cmio_chiprev)(cmi_hdl_impl_t *); const char *(*cmio_chiprevstr)(cmi_hdl_impl_t *); @@ -610,6 +614,18 @@ } static uint_t +ntv_procnodeid(cmi_hdl_impl_t *hdl) +{ + return (hdl->cmih_procnodeid); +} + +static uint_t +ntv_procnodes_per_pkg(cmi_hdl_impl_t *hdl) +{ + return (hdl->cmih_procnodes_per_pkg); +} + +static uint_t ntv_coreid(cmi_hdl_impl_t *hdl) { return (hdl->cmih_coreid); @@ -890,6 +906,18 @@ } static uint_t +xpv_procnodeid(cmi_hdl_impl_t *hdl) +{ + return (hdl->cmih_procnodeid); +} + +static uint_t +xpv_procnodes_per_pkg(cmi_hdl_impl_t *hdl) +{ + return (hdl->cmih_procnodes_per_pkg); +} + +static uint_t xpv_coreid(cmi_hdl_impl_t *hdl) { return (hdl->cmih_coreid); @@ -1213,10 +1241,20 @@ #ifdef __xpv hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_INTERPOSEOK | CMI_MSR_FLAG_WR_INTERPOSEOK; -#else /* __xpv */ + + /* + * XXX: need hypervisor support for procnodeid, for now assume + * single-node processors (procnodeid = chipid) + */ + hdl->cmih_procnodeid = xen_physcpu_chipid((xen_mc_lcpu_cookie_t)priv); + hdl->cmih_procnodes_per_pkg = 1; +#else /* __xpv */ hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_HWOK | CMI_MSR_FLAG_RD_INTERPOSEOK | CMI_MSR_FLAG_WR_HWOK | CMI_MSR_FLAG_WR_INTERPOSEOK; -#endif + hdl->cmih_procnodeid = cpuid_get_procnodeid((cpu_t *)priv); + hdl->cmih_procnodes_per_pkg = + cpuid_get_procnodes_per_pkg((cpu_t *)priv); +#endif /* __xpv */ ent = cmi_hdl_ent_lookup(chipid, coreid, strandid); if (ent->cmae_refcnt != 0 || ent->cmae_hdlp != NULL) { @@ -1508,8 +1546,10 @@ CMI_HDL_OPFUNC(model, uint_t) CMI_HDL_OPFUNC(stepping, uint_t) CMI_HDL_OPFUNC(chipid, uint_t) +CMI_HDL_OPFUNC(procnodeid, uint_t) CMI_HDL_OPFUNC(coreid, uint_t) CMI_HDL_OPFUNC(strandid, uint_t) +CMI_HDL_OPFUNC(procnodes_per_pkg, uint_t) CMI_HDL_OPFUNC(strand_apicid, uint_t) CMI_HDL_OPFUNC(chiprev, uint32_t) CMI_HDL_OPFUNC(chiprevstr, const char *) @@ -1555,6 +1595,15 @@ } /* + * Return hardware node instance; cpuid_get_procnodeid provides this directly. + */ +uint_t +cmi_ntv_hwprocnodeid(cpu_t *cp) +{ + return (cpuid_get_procnodeid(cp)); +} + +/* * Return core instance within a single chip. */ uint_t @@ -1844,8 +1893,10 @@ xpv_model, /* cmio_model */ xpv_stepping, /* cmio_stepping */ xpv_chipid, /* cmio_chipid */ + xpv_procnodeid, /* cmio_procnodeid */ xpv_coreid, /* cmio_coreid */ xpv_strandid, /* cmio_strandid */ + xpv_procnodes_per_pkg, /* cmio_procnodes_per_pkg */ xpv_strand_apicid, /* cmio_strand_apicid */ xpv_chiprev, /* cmio_chiprev */ xpv_chiprevstr, /* cmio_chiprevstr */ @@ -1874,9 +1925,11 @@ ntv_model, /* cmio_model */ ntv_stepping, /* cmio_stepping */ ntv_chipid, /* cmio_chipid */ + ntv_procnodeid, /* cmio_procnodeid */ ntv_coreid, /* cmio_coreid */ ntv_strandid, /* cmio_strandid */ - ntv_strand_apicid, /* cmio_strandid */ + ntv_procnodes_per_pkg, /* cmio_procnodes_per_pkg */ + ntv_strand_apicid, /* cmio_strand_apicid */ ntv_chiprev, /* cmio_chiprev */ ntv_chiprevstr, /* cmio_chiprevstr */ ntv_getsockettype, /* cmio_getsockettype */
--- a/usr/src/uts/i86pc/os/cpuid.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/os/cpuid.c Wed Nov 04 01:45:19 2009 -0800 @@ -26,6 +26,9 @@ * Copyright (c) 2009, Intel Corporation. * All rights reserved. */ +/* + * Portions Copyright 2009 Advanced Micro Devices, Inc. + */ /* * Various routines to handle identification @@ -49,6 +52,7 @@ #include <sys/auxv_386.h> #include <sys/bitmap.h> #include <sys/memnode.h> +#include <sys/pci_cfgspace.h> #ifdef __xpv #include <sys/hypervisor.h> @@ -153,7 +157,21 @@ */ #define NMAX_CPI_STD 6 /* eax = 0 .. 5 */ -#define NMAX_CPI_EXTD 9 /* eax = 0x80000000 .. 0x80000008 */ +#define NMAX_CPI_EXTD 0x1c /* eax = 0x80000000 .. 0x8000001b */ + +/* + * Some terminology needs to be explained: + * - Socket: Something that can be plugged into a motherboard. + * - Package: Same as socket + * - Chip: Same as socket. Note that AMD's documentation uses term "chip" + * differently: there, chip is the same as processor node (below) + * - Processor node: Some AMD processors have more than one + * "subprocessor" embedded in a package. These subprocessors (nodes) + * are fully-functional processors themselves with cores, caches, + * memory controllers, PCI configuration spaces. They are connected + * inside the package with Hypertransport links. On single-node + * processors, processor node is equivalent to chip/socket/package. + */ struct cpuid_info { uint_t cpi_pass; /* last pass completed */ @@ -167,7 +185,8 @@ uint_t cpi_family; /* fn 1: extended family */ uint_t cpi_model; /* fn 1: extended model */ uint_t cpi_step; /* fn 1: stepping */ - chipid_t cpi_chipid; /* fn 1: %ebx: chip # on ht cpus */ + chipid_t cpi_chipid; /* fn 1: %ebx: Intel: chip # */ + /* AMD: package/socket # */ uint_t cpi_brandid; /* fn 1: %ebx: brand ID */ int cpi_clogid; /* fn 1: %ebx: thread # */ uint_t cpi_ncpu_per_chip; /* fn 1: %ebx: logical cpu count */ @@ -184,8 +203,9 @@ uint_t cpi_xmaxeax; /* fn 0x80000000: %eax */ char cpi_brandstr[49]; /* fn 0x8000000[234] */ uint8_t cpi_pabits; /* fn 0x80000006: %eax */ - uint8_t cpi_vabits; /* fn 0x80000006: %eax */ - struct cpuid_regs cpi_extd[NMAX_CPI_EXTD]; /* 0x8000000[0-8] */ + uint8_t cpi_vabits; /* fn 0x80000006: %eax */ + struct cpuid_regs cpi_extd[NMAX_CPI_EXTD]; /* 0x800000XX */ + id_t cpi_coreid; /* same coreid => strands share core */ int cpi_pkgcoreid; /* core number within single package */ uint_t cpi_ncore_per_chip; /* AMD: fn 0x80000008: %ecx[7-0] */ @@ -208,6 +228,9 @@ struct mwait_info cpi_mwait; /* fn 5: monitor/mwait info */ uint32_t cpi_apicid; + uint_t cpi_procnodeid; /* AMD: nodeID on HT, Intel: chipid */ + uint_t cpi_procnodes_per_pkg; /* AMD: # of nodes in the package */ + /* Intel: 1 */ }; @@ -505,6 +528,178 @@ #endif /* __xpv */ +static void +cpuid_intel_getids(cpu_t *cpu, uint_t feature) +{ + uint_t i; + uint_t chipid_shift = 0; + uint_t coreid_shift = 0; + struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi; + + for (i = 1; i < cpi->cpi_ncpu_per_chip; i <<= 1) + chipid_shift++; + + cpi->cpi_chipid = cpi->cpi_apicid >> chipid_shift; + cpi->cpi_clogid = cpi->cpi_apicid & ((1 << chipid_shift) - 1); + + if (feature & X86_CMP) { + /* + * Multi-core (and possibly multi-threaded) + * processors. + */ + uint_t ncpu_per_core; + if (cpi->cpi_ncore_per_chip == 1) + ncpu_per_core = cpi->cpi_ncpu_per_chip; + else if (cpi->cpi_ncore_per_chip > 1) + ncpu_per_core = cpi->cpi_ncpu_per_chip / + cpi->cpi_ncore_per_chip; + /* + * 8bit APIC IDs on dual core Pentiums + * look like this: + * + * +-----------------------+------+------+ + * | Physical Package ID | MC | HT | + * +-----------------------+------+------+ + * <------- chipid --------> + * <------- coreid ---------------> + * <--- clogid --> + * <------> + * pkgcoreid + * + * Where the number of bits necessary to + * represent MC and HT fields together equals + * to the minimum number of bits necessary to + * store the value of cpi->cpi_ncpu_per_chip. + * Of those bits, the MC part uses the number + * of bits necessary to store the value of + * cpi->cpi_ncore_per_chip. + */ + for (i = 1; i < ncpu_per_core; i <<= 1) + coreid_shift++; + cpi->cpi_coreid = cpi->cpi_apicid >> coreid_shift; + cpi->cpi_pkgcoreid = cpi->cpi_clogid >> coreid_shift; + } else if (feature & X86_HTT) { + /* + * Single-core multi-threaded processors. + */ + cpi->cpi_coreid = cpi->cpi_chipid; + cpi->cpi_pkgcoreid = 0; + } + cpi->cpi_procnodeid = cpi->cpi_chipid; +} + +static void +cpuid_amd_getids(cpu_t *cpu) +{ + int first_half, mnc, coreidsz; + uint32_t nb_caps_reg; + uint_t node2_1; + struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi; + + /* + * AMD CMP chips currently have a single thread per core. + * + * Since no two cpus share a core we must assign a distinct coreid + * per cpu, and we do this by using the cpu_id. This scheme does not, + * however, guarantee that sibling cores of a chip will have sequential + * coreids starting at a multiple of the number of cores per chip - + * that is usually the case, but if the ACPI MADT table is presented + * in a different order then we need to perform a few more gymnastics + * for the pkgcoreid. + * + * All processors in the system have the same number of enabled + * cores. Cores within a processor are always numbered sequentially + * from 0 regardless of how many or which are disabled, and there + * is no way for operating system to discover the real core id when some + * are disabled. + */ + + cpi->cpi_coreid = cpu->cpu_id; + + if (cpi->cpi_xmaxeax >= 0x80000008) { + + coreidsz = BITX((cpi)->cpi_extd[8].cp_ecx, 15, 12); + + /* + * In AMD parlance chip is really a node while Solaris + * sees chip as equivalent to socket/package. + */ + cpi->cpi_ncore_per_chip = + BITX((cpi)->cpi_extd[8].cp_ecx, 7, 0) + 1; + if (coreidsz == 0) + /* Use legacy method */ + mnc = cpi->cpi_ncore_per_chip; + else + mnc = (1 << coreidsz); + } else { + /* Assume single-core part */ + cpi->cpi_ncore_per_chip = mnc = 1; + } + + cpi->cpi_clogid = cpi->cpi_pkgcoreid = cpi->cpi_apicid & (mnc - 1); + cpi->cpi_ncpu_per_chip = cpi->cpi_ncore_per_chip; + + /* Get nodeID */ + if (cpi->cpi_family == 0xf) { + cpi->cpi_procnodeid = BITX(cpi->cpi_apicid, 3, mnc-1); + cpi->cpi_chipid = cpi->cpi_procnodeid; + } else if (cpi->cpi_family == 0x10) { + /* + * See if we are a multi-node processor. + * All processors in the system have the same number of nodes + */ + nb_caps_reg = pci_getl_func(0, 24, 3, 0xe8); + if ((cpi->cpi_model < 8) || BITX(nb_caps_reg, 29, 29) == 0) { + /* Single-node */ + cpi->cpi_procnodeid = BITX(cpi->cpi_apicid, 5, 3); + cpi->cpi_chipid = cpi->cpi_procnodeid; + } else { + + /* + * Multi-node revision D (2 nodes per package + * are supported) + */ + cpi->cpi_procnodes_per_pkg = 2; + + first_half = (cpi->cpi_pkgcoreid <= + (cpi->cpi_ncore_per_chip/2 - 1)); + + if (cpi->cpi_apicid == cpi->cpi_pkgcoreid) { + /* We are BSP */ + cpi->cpi_procnodeid = (first_half ? 0 : 1); + cpi->cpi_chipid = cpi->cpi_procnodeid >> 1; + } else { + + /* We are AP */ + /* NodeId[2:1] bits to use for reading F3xe8 */ + node2_1 = BITX(cpi->cpi_apicid, 5, 4) << 1; + + nb_caps_reg = + pci_getl_func(0, 24 + node2_1, 3, 0xe8); + + /* + * Check IntNodeNum bit (31:30, but bit 31 is + * always 0 on dual-node processors) + */ + if (BITX(nb_caps_reg, 30, 30) == 0) + cpi->cpi_procnodeid = node2_1 + + !first_half; + else + cpi->cpi_procnodeid = node2_1 + + first_half; + + cpi->cpi_chipid = cpi->cpi_procnodeid >> 1; + } + } + } else if (cpi->cpi_family >= 0x11) { + cpi->cpi_procnodeid = (cpi->cpi_apicid >> coreidsz) & 7; + cpi->cpi_chipid = cpi->cpi_procnodeid; + } else { + cpi->cpi_procnodeid = 0; + cpi->cpi_chipid = cpi->cpi_procnodeid; + } +} + uint_t cpuid_pass1(cpu_t *cpu) { @@ -1124,6 +1319,9 @@ if (cpi->cpi_ncpu_per_chip == cpi->cpi_ncore_per_chip) feature &= ~X86_HTT; + cpi->cpi_apicid = CPI_APIC_ID(cpi); + cpi->cpi_procnodes_per_pkg = 1; + if ((feature & (X86_HTT | X86_CMP)) == 0) { /* * Single-core single-threaded processors. @@ -1132,115 +1330,26 @@ cpi->cpi_clogid = 0; cpi->cpi_coreid = cpu->cpu_id; cpi->cpi_pkgcoreid = 0; + if (cpi->cpi_vendor == X86_VENDOR_AMD) + cpi->cpi_procnodeid = BITX(cpi->cpi_apicid, 3, 0); + else + cpi->cpi_procnodeid = cpi->cpi_chipid; } else if (cpi->cpi_ncpu_per_chip > 1) { - uint_t i; - uint_t chipid_shift = 0; - uint_t coreid_shift = 0; - uint_t apic_id = CPI_APIC_ID(cpi); - - for (i = 1; i < cpi->cpi_ncpu_per_chip; i <<= 1) - chipid_shift++; - cpi->cpi_chipid = apic_id >> chipid_shift; - cpi->cpi_clogid = apic_id & ((1 << chipid_shift) - 1); - - if (cpi->cpi_vendor == X86_VENDOR_Intel) { - if (feature & X86_CMP) { - /* - * Multi-core (and possibly multi-threaded) - * processors. - */ - uint_t ncpu_per_core; - if (cpi->cpi_ncore_per_chip == 1) - ncpu_per_core = cpi->cpi_ncpu_per_chip; - else if (cpi->cpi_ncore_per_chip > 1) - ncpu_per_core = cpi->cpi_ncpu_per_chip / - cpi->cpi_ncore_per_chip; - /* - * 8bit APIC IDs on dual core Pentiums - * look like this: - * - * +-----------------------+------+------+ - * | Physical Package ID | MC | HT | - * +-----------------------+------+------+ - * <------- chipid --------> - * <------- coreid ---------------> - * <--- clogid --> - * <------> - * pkgcoreid - * - * Where the number of bits necessary to - * represent MC and HT fields together equals - * to the minimum number of bits necessary to - * store the value of cpi->cpi_ncpu_per_chip. - * Of those bits, the MC part uses the number - * of bits necessary to store the value of - * cpi->cpi_ncore_per_chip. - */ - for (i = 1; i < ncpu_per_core; i <<= 1) - coreid_shift++; - cpi->cpi_coreid = apic_id >> coreid_shift; - cpi->cpi_pkgcoreid = cpi->cpi_clogid >> - coreid_shift; - } else if (feature & X86_HTT) { - /* - * Single-core multi-threaded processors. - */ - cpi->cpi_coreid = cpi->cpi_chipid; - cpi->cpi_pkgcoreid = 0; - } - } else if (cpi->cpi_vendor == X86_VENDOR_AMD) { - /* - * AMD CMP chips currently have a single thread per - * core, with 2 cores on family 0xf and 2, 3 or 4 - * cores on family 0x10. - * - * Since no two cpus share a core we must assign a - * distinct coreid per cpu, and we do this by using - * the cpu_id. This scheme does not, however, - * guarantee that sibling cores of a chip will have - * sequential coreids starting at a multiple of the - * number of cores per chip - that is usually the - * case, but if the ACPI MADT table is presented - * in a different order then we need to perform a - * few more gymnastics for the pkgcoreid. - * - * In family 0xf CMPs there are 2 cores on all nodes - * present - no mixing of single and dual core parts. - * - * In family 0x10 CMPs cpuid fn 2 ECX[15:12] - * "ApicIdCoreIdSize[3:0]" tells us how - * many least-significant bits in the ApicId - * are used to represent the core number - * within the node. Cores are always - * numbered sequentially from 0 regardless - * of how many or which are disabled, and - * there seems to be no way to discover the - * real core id when some are disabled. - */ - cpi->cpi_coreid = cpu->cpu_id; - - if (cpi->cpi_family == 0x10 && - cpi->cpi_xmaxeax >= 0x80000008) { - int coreidsz = - BITX((cpi)->cpi_extd[8].cp_ecx, 15, 12); - - cpi->cpi_pkgcoreid = - apic_id & ((1 << coreidsz) - 1); - } else { - cpi->cpi_pkgcoreid = cpi->cpi_clogid; - } - } else { + if (cpi->cpi_vendor == X86_VENDOR_Intel) + cpuid_intel_getids(cpu, feature); + else if (cpi->cpi_vendor == X86_VENDOR_AMD) + cpuid_amd_getids(cpu); + else { /* * All other processors are currently * assumed to have single cores. */ cpi->cpi_coreid = cpi->cpi_chipid; cpi->cpi_pkgcoreid = 0; + cpi->cpi_procnodeid = cpi->cpi_chipid; } } - cpi->cpi_apicid = CPI_APIC_ID(cpi); - /* * Synthesize chip "revision" and socket type */ @@ -2556,6 +2665,20 @@ return (cpu->cpu_m.mcpu_cpi->cpi_clogid); } +uint_t +cpuid_get_procnodeid(cpu_t *cpu) +{ + ASSERT(cpuid_checkpass(cpu, 1)); + return (cpu->cpu_m.mcpu_cpi->cpi_procnodeid); +} + +uint_t +cpuid_get_procnodes_per_pkg(cpu_t *cpu) +{ + ASSERT(cpuid_checkpass(cpu, 1)); + return (cpu->cpu_m.mcpu_cpi->cpi_procnodes_per_pkg); +} + /*ARGSUSED*/ int cpuid_have_cr8access(cpu_t *cpu)
--- a/usr/src/uts/i86pc/os/lgrpplat.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/os/lgrpplat.c Wed Nov 04 01:45:19 2009 -0800 @@ -1152,12 +1152,12 @@ /* * SRAT doesn't exist, isn't enabled, or there was an error processing - * it, so return chip ID for Opteron and -1 otherwise. + * it, so return node ID for Opteron and -1 otherwise. */ if (srat_ptr == NULL || !lgrp_plat_srat_enable || lgrp_plat_srat_error) { if (is_opteron()) - return (pg_plat_hw_instance_id(cp, PGHW_CHIP)); + return (pg_plat_hw_instance_id(cp, PGHW_PROCNODE)); return (-1); }
--- a/usr/src/uts/i86pc/os/mp_machdep.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/i86pc/os/mp_machdep.c Wed Nov 04 01:45:19 2009 -0800 @@ -231,6 +231,11 @@ } else { return (0); } + case PGHW_PROCNODE: + if (cpuid_get_procnodes_per_pkg(cp) > 1) + return (1); + else + return (0); case PGHW_CHIP: if (x86_feature & (X86_CMP|X86_HTT)) return (1); @@ -286,6 +291,8 @@ return (cpuid_get_coreid(cpu)); case PGHW_CACHE: return (cpuid_get_last_lvl_cacheid(cpu)); + case PGHW_PROCNODE: + return (cpuid_get_procnodeid(cpu)); case PGHW_CHIP: return (cpuid_get_chipid(cpu)); case PGHW_POW_ACTIVE: @@ -309,6 +316,7 @@ static pghw_type_t hw_hier[] = { PGHW_IPIPE, PGHW_CACHE, + PGHW_PROCNODE, PGHW_CHIP, PGHW_POW_IDLE, PGHW_POW_ACTIVE, @@ -1654,6 +1662,7 @@ { if (hw == PGHW_IPIPE || hw == PGHW_FPU || + hw == PGHW_PROCNODE || hw == PGHW_CHIP) return (1); else
--- a/usr/src/uts/intel/io/devfm_machdep.c Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/intel/io/devfm_machdep.c Wed Nov 04 01:45:19 2009 -0800 @@ -186,6 +186,10 @@ (int32_t)cmi_hdl_stepping(hdl), FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32, (int32_t)fm_chipid, + FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32, + (int32_t)cmi_hdl_procnodes_per_pkg(hdl), + FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32, + (int32_t)cmi_hdl_procnodeid(hdl), FM_PHYSCPU_INFO_CORE_ID, DATA_TYPE_INT32, (int32_t)cmi_hdl_coreid(hdl), FM_PHYSCPU_INFO_STRAND_ID, DATA_TYPE_INT32,
--- a/usr/src/uts/intel/sys/cpu_module.h Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/intel/sys/cpu_module.h Wed Nov 04 01:45:19 2009 -0800 @@ -150,10 +150,11 @@ extern uint_t cmi_hdl_model(cmi_hdl_t); extern uint_t cmi_hdl_stepping(cmi_hdl_t); extern uint_t cmi_hdl_chipid(cmi_hdl_t); -extern uint_t cmi_hdl_dieid(cmi_hdl_t); +extern uint_t cmi_hdl_procnodeid(cmi_hdl_t); extern uint_t cmi_hdl_coreid(cmi_hdl_t); extern uint_t cmi_hdl_strandid(cmi_hdl_t); extern uint_t cmi_hdl_strand_apicid(cmi_hdl_t); +extern uint_t cmi_hdl_procnodes_per_pkg(cmi_hdl_t); extern boolean_t cmi_hdl_is_cmt(cmi_hdl_t); extern uint32_t cmi_hdl_chiprev(cmi_hdl_t); extern const char *cmi_hdl_chiprevstr(cmi_hdl_t); @@ -168,6 +169,7 @@ #ifndef __xpv extern uint_t cmi_ntv_hwchipid(cpu_t *); +extern uint_t cmi_ntv_hwprocnodeid(cpu_t *); extern uint_t cmi_ntv_hwcoreid(cpu_t *); extern uint_t cmi_ntv_hwstrandid(cpu_t *); #endif /* __xpv */
--- a/usr/src/uts/intel/sys/x86_archext.h Tue Nov 03 23:15:19 2009 -0800 +++ b/usr/src/uts/intel/sys/x86_archext.h Wed Nov 04 01:45:19 2009 -0800 @@ -622,6 +622,8 @@ extern int cpuid_get_pkgcoreid(struct cpu *); extern int cpuid_get_clogid(struct cpu *); extern uint32_t cpuid_get_apicid(struct cpu *); +extern uint_t cpuid_get_procnodeid(struct cpu *cpu); +extern uint_t cpuid_get_procnodes_per_pkg(struct cpu *cpu); extern int cpuid_is_cmt(struct cpu *); extern int cpuid_syscall32_insn(struct cpu *); extern int getl2cacheinfo(struct cpu *, int *, int *, int *);