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 *);