changeset 3681:d93cfde2f771

6519375 refactored the mdesc code in cpu scheme, platform-cpu.so and chip.so into a single code base 6520142 sun4v motherboard/chip enums leaking memory 6520501 libtopo exports a set of errors associated with node methods
author vn83148
date Mon, 19 Feb 2007 20:47:33 -0800
parents 773fb303fd36
children 48f0fd311ddb
files usr/src/cmd/fm/schemes/cpu/amd64/Makefile usr/src/cmd/fm/schemes/cpu/cpu.c usr/src/cmd/fm/schemes/cpu/i386/Makefile usr/src/cmd/fm/schemes/cpu/sparc/Makefile usr/src/cmd/fm/schemes/cpu/sparc/cpu_mdesc.c usr/src/cmd/fm/schemes/cpu/sparc/cpu_mdesc.h usr/src/cmd/fm/schemes/cpu/sparcv9/Makefile usr/src/lib/fm/topo/libtopo/Makefile.com usr/src/lib/fm/topo/libtopo/common/libtopo.h usr/src/lib/fm/topo/libtopo/common/mkerror.sh usr/src/lib/fm/topo/libtopo/common/topo_error.h usr/src/lib/fm/topo/libtopo/common/topo_fmri.c usr/src/lib/fm/topo/libtopo/common/topo_method.h usr/src/lib/fm/topo/libtopo/common/topo_mod.h usr/src/lib/fm/topo/modules/sun4/chip/Makefile.chip usr/src/lib/fm/topo/modules/sun4u/chip/Makefile usr/src/lib/fm/topo/modules/sun4v/chip/Makefile usr/src/lib/fm/topo/modules/sun4v/chip/chip_sun4v.c usr/src/lib/fm/topo/modules/sun4v/motherboard/motherboard.c usr/src/lib/fm/topo/modules/sun4v/platform-cpu/Makefile usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu.c usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu_mdesc.c usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu_mdesc.h
diffstat 23 files changed, 813 insertions(+), 895 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/fm/schemes/cpu/amd64/Makefile	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/cmd/fm/schemes/cpu/amd64/Makefile	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -30,7 +30,10 @@
 include $(SRC)/Makefile.master.64
 
 SRCS = cpu.c
-LDFLAGS += -lkstat
+LDFLAGS += -lkstat \
+	-L$(ROOTLIB)/fm/$(MACH64) -ltopo
+LDFLAGS += -R/usr/lib/fm/$(MACH64)
+
 
 include ../../Makefile.targ
 
--- a/usr/src/cmd/fm/schemes/cpu/cpu.c	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/cmd/fm/schemes/cpu/cpu.c	Mon Feb 19 20:47:33 2007 -0800
@@ -29,25 +29,16 @@
 #include <sys/types.h>
 #include <sys/processor.h>
 #include <fm/fmd_fmri.h>
+#include <fm/libtopo.h>
 
 #include <strings.h>
 #include <errno.h>
 #include <kstat.h>
 
-#ifdef	sparc
-#include <cpu_mdesc.h>
-#include <sys/fm/ldom.h>
-#endif
-
 /*
  * The scheme plugin for cpu FMRIs.
  */
 
-#ifdef sparc
-cpu_t cpu;
-static ldom_hdl_t *cpu_scheme_lhp;
-#endif /* sparc */
-
 ssize_t
 fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
 {
@@ -161,12 +152,7 @@
 	int err;
 	uint64_t serial = 0;
 
-#ifdef	sparc
-	if (cpu.cpu_mdesc_cpus != NULL)
-		err = cpu_get_serialid_mdesc(cpuid, &serial);
-	else
-#endif	/* sparc */
-		err = cpu_get_serialid_kstat(cpuid, &serial);
+	err = cpu_get_serialid_kstat(cpuid, &serial);
 
 	(void) snprintf(serbuf, len, "%llX", (u_longlong_t)serial);
 	return (err);
@@ -175,12 +161,7 @@
 static int
 cpu_get_serialid_V0(uint32_t cpuid, uint64_t *serialidp)
 {
-#ifdef  sparc
-	if (cpu.cpu_mdesc_cpus != NULL)
-		return (cpu_get_serialid_mdesc(cpuid, serialidp));
-	else
-#endif  /* sparc */
-		return (cpu_get_serialid_kstat(cpuid, serialidp));
+	return (cpu_get_serialid_kstat(cpuid, serialidp));
 }
 
 int
@@ -190,12 +171,19 @@
 	uint32_t cpuid;
 	uint64_t serialid;
 	char *serstr, serbuf[21]; /* sizeof (UINT64_MAX) + '\0' */
-	int rc;
+	int rc, err;
 
 	if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 ||
 	    nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0)
 		return (fmd_fmri_set_errno(EINVAL));
 
+	/*
+	 * If the cpu-scheme topology exports this method expand(), invoke it.
+	 */
+	rc = topo_fmri_expand(fmd_fmri_topology(TOPO_VERSION), nvl, &err);
+	if (err != ETOPO_METHOD_NOTSUP)
+		return (rc);
+
 	if (version == CPU_SCHEME_VERSION0) {
 		if ((rc = nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID,
 		    &serialid)) != 0) {
@@ -209,32 +197,6 @@
 			    serialid)) != 0)
 				return (fmd_fmri_set_errno(rc));
 		}
-#ifdef sparc
-		if (cpu.cpu_mdesc_cpus != NULL) {
-			md_cpumap_t *mcmp = cpu_find_cpumap(cpuid);
-			if (mcmp != NULL) {
-			    if (strcmp(mcmp->cpumap_cpufrudn, "") == 0) {
-				(void) nvlist_add_string(nvl,
-				    FM_FMRI_HC_PART, mcmp->cpumap_cpufrupn);
-			    } else {
-				size_t ss = strlen(mcmp->cpumap_cpufrupn) +
-				    strlen(mcmp->cpumap_cpufrudn) + 1;
-				char *sp = fmd_fmri_alloc(ss);
-				sp = strcpy(sp, mcmp->cpumap_cpufrupn);
-				sp = strncat(sp, mcmp->cpumap_cpufrudn,
-				    strlen(mcmp->cpumap_cpufrudn) + 1);
-				(void) nvlist_add_string(nvl,
-				    FM_FMRI_HC_PART, sp);
-				fmd_fmri_free(sp, ss);
-			    }
-			    (void) nvlist_add_string(nvl,
-				FM_FMRI_CPU_CPUFRU, mcmp->cpumap_cpufru);
-			    nvl->nvl_nvflag = NV_UNIQUE_NAME_TYPE;
-			    (void) nvlist_add_string(nvl, FM_FMRI_HC_SERIAL_ID,
-				mcmp->cpumap_cpufrusn);
-			}
-		}
-#endif	/* sparc */
 	} else if (version == CPU_SCHEME_VERSION1) {
 		if ((rc = nvlist_lookup_string(nvl, FM_FMRI_CPU_SERIAL_ID,
 		    &serstr)) != 0) {
@@ -258,7 +220,7 @@
 int
 fmd_fmri_present(nvlist_t *nvl)
 {
-	int rc;
+	int rc, err;
 	uint8_t version;
 	uint32_t cpuid;
 	uint64_t nvlserid, curserid;
@@ -268,6 +230,13 @@
 	    nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0)
 		return (fmd_fmri_set_errno(EINVAL));
 
+	/*
+	 * If the cpu-scheme topology exports this method present(), invoke it.
+	 */
+	rc = topo_fmri_present(fmd_fmri_topology(TOPO_VERSION), nvl, &err);
+	if (err != ETOPO_METHOD_NOTSUP)
+		return (rc);
+
 	if (version == CPU_SCHEME_VERSION0) {
 		if (nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID,
 		    &nvlserid) != 0)
@@ -300,6 +269,7 @@
 int
 fmd_fmri_unusable(nvlist_t *nvl)
 {
+	int rc, err;
 	uint8_t version;
 	uint32_t cpuid;
 
@@ -308,30 +278,12 @@
 	    nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0)
 		return (fmd_fmri_set_errno(EINVAL));
 
-#ifdef sparc
-	{
-		int cpustatus = ldom_fmri_status(cpu_scheme_lhp, nvl);
-
-		return (cpustatus == P_FAULTED || (cpustatus == P_OFFLINE &&
-				ldom_major_version(cpu_scheme_lhp) == 1));
-	}
-#else
-	return (p_online(cpuid, P_STATUS) == P_FAULTED);
-#endif
-}
+	/*
+	 * If the cpu-scheme topology exports this method unusable(), invoke it.
+	 */
+	rc = topo_fmri_unusable(fmd_fmri_topology(TOPO_VERSION), nvl, &err);
+	if (err != ETOPO_METHOD_NOTSUP)
+		return (rc);
 
-#ifdef	sparc
-int
-fmd_fmri_init(void)
-{
-	cpu_scheme_lhp = ldom_init(fmd_fmri_alloc, fmd_fmri_free);
-	return (cpu_mdesc_init(cpu_scheme_lhp));
+	return (p_online(cpuid, P_STATUS) == P_FAULTED);
 }
-
-void
-fmd_fmri_fini(void)
-{
-	cpu_mdesc_fini();
-	ldom_fini(cpu_scheme_lhp);
-}
-#endif	/* sparc */
--- a/usr/src/cmd/fm/schemes/cpu/i386/Makefile	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/cmd/fm/schemes/cpu/i386/Makefile	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -29,7 +29,9 @@
 include ../../Makefile.com
 
 SRCS = cpu.c
-LDLIBS += -lkstat
+LDLIBS += -lkstat \
+	-L$(ROOTLIB)/fm -ltopo
+LDFLAGS += -R/usr/lib/fm
 
 include ../../Makefile.targ
 
--- a/usr/src/cmd/fm/schemes/cpu/sparc/Makefile	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/cmd/fm/schemes/cpu/sparc/Makefile	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -28,10 +28,10 @@
 
 include ../../Makefile.com
 
-SRCS = cpu.c cpu_mdesc.c
+SRCS = cpu.c
 
-CPPFLAGS += -I. -I$(ROOT)/usr/platform/sun4v/include
-LDLIBS += -L$(ROOTLIB)/fm -lmdesc -lkstat -lldom
+LDLIBS += -lkstat \
+	-L$(ROOTLIB)/fm -ltopo
 LDFLAGS += -R/usr/lib/fm
 
 include ../../Makefile.targ
--- a/usr/src/cmd/fm/schemes/cpu/sparc/cpu_mdesc.c	Mon Feb 19 05:28:47 2007 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 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/processor.h>
-#include <fm/fmd_fmri.h>
-#include <sys/param.h>
-#include <string.h>
-#include <errno.h>
-#include <cpu_mdesc.h>
-
-md_cpumap_t *
-cpu_find_cpumap(uint32_t cpuid) {
-	int i;
-	md_cpumap_t *mcmp;
-
-	for (i = 0, mcmp = cpu.cpu_mdesc_cpus;
-	    i < cpu.cpu_mdesc_ncpus; i++, mcmp++) {
-		if (cpuid == mcmp->cpumap_pid) {
-			return (mcmp);
-		}
-	}
-	return (NULL);
-}
-
-int
-cpu_get_serialid_mdesc(uint32_t cpuid, uint64_t *serialidp)
-{
-	md_cpumap_t *mcmp;
-	if ((mcmp = cpu_find_cpumap(cpuid)) != NULL) {
-		*serialidp = mcmp->cpumap_serialno;
-		return (0);
-	}
-	return (fmd_fmri_set_errno(ENOENT));
-}
-
-int
-cpu_mdesc_init(ldom_hdl_t *lhp)
-{
-	md_t *mdp;
-	mde_cookie_t *listp;
-	md_cpumap_t *mcmp;
-	uint64_t *bufp;
-	int num_nodes, idx;
-	ssize_t bufsiz = 0;
-	char *type, *cpufru, *cpufrusn, *cpufrupn, *cpufrudn;
-	int num_comps = 0;
-	uint64_t tl;
-
-	if ((bufsiz = ldom_get_core_md(lhp, &bufp)) > 0) {
-		if ((mdp = md_init_intern(bufp, fmd_fmri_alloc,
-					fmd_fmri_free)) == NULL) {
-			fmd_fmri_free(bufp, (size_t)bufsiz);
-			return (0);
-		}
-	} else {
-		return (0);
-	}
-
-	num_nodes = md_node_count(mdp);
-	listp = fmd_fmri_alloc(sizeof (mde_cookie_t) * num_nodes);
-
-	num_comps = md_scan_dag(mdp,
-	    MDE_INVAL_ELEM_COOKIE,
-	    md_find_name(mdp, "component"),
-	    md_find_name(mdp, "fwd"),
-	    listp);
-
-	if (num_comps == 0) {
-		cpu.cpu_mdesc_ncpus = md_scan_dag(mdp,
-		    MDE_INVAL_ELEM_COOKIE,
-		    md_find_name(mdp, "cpu"),
-		    md_find_name(mdp, "fwd"),
-		    listp);
-
-		cpu.cpu_mdesc_cpus = fmd_fmri_alloc(cpu.cpu_mdesc_ncpus *
-		    sizeof (md_cpumap_t));
-
-		for (idx = 0, mcmp = cpu.cpu_mdesc_cpus;
-		    idx < cpu.cpu_mdesc_ncpus;
-		    idx++, mcmp++) {
-			uint64_t tl;
-
-			if (md_get_prop_val(mdp, listp[idx], "id", &tl) < 0)
-				tl = (uint64_t)-1; /* invalid value */
-			mcmp->cpumap_id = tl;
-
-			if (md_get_prop_val(mdp, listp[idx], "pid", &tl) < 0)
-				tl = mcmp->cpumap_id;
-			mcmp->cpumap_pid = tl;
-
-			if (md_get_prop_val(mdp, listp[idx], "serial#",
-			    &mcmp->cpumap_serialno) < 0)
-				mcmp->cpumap_serialno = 0;
-
-			if (md_get_prop_str(mdp, listp[idx], "cpufru",
-			    &cpufru) < 0)
-				cpufru = "mb";
-			mcmp->cpumap_cpufru = fmd_fmri_strdup(cpufru);
-
-			if (md_get_prop_str(mdp, listp[idx], "cpufru-serial#",
-			    &cpufrusn) < 0)
-				cpufrusn = "";
-			mcmp->cpumap_cpufrusn = fmd_fmri_strdup(cpufrusn);
-
-			if (md_get_prop_str(mdp, listp[idx], "cpufru-part#",
-			    &cpufrupn) < 0)
-				cpufrupn = "";
-			mcmp->cpumap_cpufrupn = fmd_fmri_strdup(cpufrupn);
-			cpufrudn = "";
-			mcmp->cpumap_cpufrudn = fmd_fmri_strdup(cpufrudn);
-		}
-	} else {
-		uint64_t procsn;
-		mde_cookie_t procnode = MDE_INVAL_ELEM_COOKIE;
-
-		for (idx = 0; idx < num_comps; idx++) {
-		    if (md_get_prop_str(mdp, listp[idx], "type", &type) < 0)
-			continue;
-		    if (strcmp(type, "systemboard") == 0) {
-			cpufru = "MB";
-			if (md_get_prop_str(mdp, listp[idx], "serial_number",
-			    &cpufrusn) < 0)
-				cpufrusn = "";
-			if (md_get_prop_str(mdp, listp[idx], "part_number",
-			    &cpufrupn) < 0)
-				cpufrupn = "";
-			if (md_get_prop_str(mdp, listp[idx], "dash_number",
-			    &cpufrudn) < 0)
-				cpufrudn = "";
-			break;
-		    }
-		}
-
-		for (idx = 0; idx < num_comps; idx++) {
-		    if (md_get_prop_str(mdp, listp[idx], "type", &type) < 0)
-			continue;
-		    if (strcmp(type, "processor") == 0) {
-			if (md_get_prop_val(mdp, listp[idx], "serial_number",
-			    &procsn) < 0)
-				procsn = 0;
-			procnode = listp[idx];
-			break;
-		    }
-		}
-
-		/*
-		 * scan the procnode to find all strand nodes
-		 */
-		cpu.cpu_mdesc_ncpus = md_scan_dag(mdp, procnode,
-			md_find_name(mdp, "component"),
-			md_find_name(mdp, "fwd"),
-			listp);
-
-		cpu.cpu_mdesc_cpus = fmd_fmri_alloc(cpu.cpu_mdesc_ncpus *
-		    sizeof (md_cpumap_t));
-
-		mcmp = cpu.cpu_mdesc_cpus;
-		for (idx = 0; idx < cpu.cpu_mdesc_ncpus; idx++) {
-			if (md_get_prop_str(mdp, listp[idx], "type", &type) < 0)
-				continue;
-			if (strcmp(type, "strand") == 0) {
-				if (md_get_prop_val(mdp, listp[idx], "id",
-				    &tl) < 0)
-					tl = (uint64_t)-1;
-				mcmp->cpumap_id = tl;
-
-				mcmp->cpumap_pid = mcmp->cpumap_id;
-
-				mcmp->cpumap_serialno = procsn;
-				mcmp->cpumap_cpufru = fmd_fmri_strdup(cpufru);
-				mcmp->cpumap_cpufrusn =
-				    fmd_fmri_strdup(cpufrusn);
-				mcmp->cpumap_cpufrupn =
-				    fmd_fmri_strdup(cpufrupn);
-				mcmp->cpumap_cpufrudn =
-				    fmd_fmri_strdup(cpufrudn);
-				mcmp++;
-			}
-		}
-
-	}
-
-	fmd_fmri_free(listp, sizeof (mde_cookie_t) * num_nodes);
-	fmd_fmri_free(bufp, (size_t)bufsiz);
-	(void) md_fini(mdp);
-
-	return (0);
-}
-
-void
-cpu_mdesc_fini(void)
-{
-	if (cpu.cpu_mdesc_cpus != NULL) {
-		int idx;
-		md_cpumap_t *mcmp;
-		for (idx = 0, mcmp = cpu.cpu_mdesc_cpus;
-		    idx < cpu.cpu_mdesc_ncpus;
-		    idx++, mcmp++) {
-			fmd_fmri_strfree(mcmp->cpumap_cpufru);
-			fmd_fmri_strfree(mcmp->cpumap_cpufrusn);
-			fmd_fmri_strfree(mcmp->cpumap_cpufrupn);
-		}
-		fmd_fmri_free(cpu.cpu_mdesc_cpus,
-		    cpu.cpu_mdesc_ncpus * sizeof (md_cpumap_t));
-	}
-}
--- a/usr/src/cmd/fm/schemes/cpu/sparc/cpu_mdesc.h	Mon Feb 19 05:28:47 2007 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_CPU_MDESC_H
-#define	_CPU_MDESC_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/mdesc.h>
-#include <sys/fm/ldom.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-typedef struct md_cpumap {
-	uint32_t cpumap_id;
-	uint32_t cpumap_pid;
-	uint64_t cpumap_serialno;
-	char *cpumap_cpufru;
-	char *cpumap_cpufrusn;
-	char *cpumap_cpufrupn;
-	char *cpumap_cpufrudn;
-} md_cpumap_t;
-
-typedef struct cpu {
-	md_cpumap_t *cpu_mdesc_cpus;	/* ptr to array of cpu maps */
-	uint32_t cpu_mdesc_ncpus;	/* number of cpu maps */
-} cpu_t;
-
-extern cpu_t cpu;
-
-extern int cpu_get_serialid_mdesc(uint32_t, uint64_t *);
-extern md_cpumap_t *cpu_find_cpumap(uint32_t);
-extern int cpu_mdesc_init(ldom_hdl_t *lhp);
-extern void cpu_mdesc_fini(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* _CPU_MDESC_H */
--- a/usr/src/cmd/fm/schemes/cpu/sparcv9/Makefile	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/cmd/fm/schemes/cpu/sparcv9/Makefile	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -29,10 +29,9 @@
 include ../../Makefile.com
 include $(SRC)/Makefile.master.64
 
-SRCS = cpu.c cpu_mdesc.c
-CPPFLAGS += -I../sparc -I$(ROOT)/usr/platform/sun4v/include
+SRCS = cpu.c
 LDLIBS += -lkstat \
-	-L$(ROOTLIB)/fm/$(MACH64) -lmdesc -lldom
+	-L$(ROOTLIB)/fm/$(MACH64) -ltopo
 LDFLAGS += -R/usr/lib/fm/$(MACH64)
 
 include ../../Makefile.targ
--- a/usr/src/lib/fm/topo/libtopo/Makefile.com	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/libtopo/Makefile.com	Mon Feb 19 20:47:33 2007 -0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -104,6 +104,7 @@
 ../common/topo_error.c: ../common/mkerror.sh ../common/topo_error.h
 	sh ../common/mkerror.sh liberrors < ../common/topo_error.h > $@
 	sh ../common/mkerror.sh properrors < ../common/libtopo.h >> $@
+	sh ../common/mkerror.sh methoderrors < ../common/libtopo.h >> $@
 	sh ../common/mkerror.sh moderrors < ../common/topo_mod.h >> $@
 
 include ../../../../Makefile.targ
--- a/usr/src/lib/fm/topo/libtopo/common/libtopo.h	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/libtopo.h	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -122,6 +122,7 @@
  */
 extern int topo_fmri_present(topo_hdl_t *, nvlist_t *, int *);
 extern int topo_fmri_contains(topo_hdl_t *, nvlist_t *, nvlist_t *, int *);
+extern int topo_fmri_expand(topo_hdl_t *, nvlist_t *, int *);
 extern int topo_fmri_unusable(topo_hdl_t *, nvlist_t *, int *);
 extern int topo_fmri_nvl2str(topo_hdl_t *, nvlist_t *, char **, int *);
 extern int topo_fmri_str2nvl(topo_hdl_t *, const char *, nvlist_t **, int *);
@@ -250,6 +251,18 @@
     ETOPO_PROP_END	/* end of prop errno list (to ease auto-merge) */
 } topo_prop_errno_t;
 
+/*
+ * Similar to the above, this enum defines a set of errors associated with node
+ * methods.
+ */
+typedef enum topo_method_errno {
+    ETOPO_METHOD_UNKNOWN = 4000, /* unknown topo method error */
+    ETOPO_METHOD_INVAL, /* invalid method registration */
+    ETOPO_METHOD_NOTSUP, /* method not supported */
+    ETOPO_METHOD_FAIL  /* method failed */
+} topo_method_errno_t;
+
+
 extern const char *topo_strerror(int);
 extern void topo_debug_set(topo_hdl_t *, const char *, const char *);
 extern void *topo_hdl_alloc(topo_hdl_t *, size_t);
--- a/usr/src/lib/fm/topo/libtopo/common/mkerror.sh	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/mkerror.sh	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"@(#)mkerror.sh	1.1	06/02/11 SMI"
@@ -34,7 +34,7 @@
 if [ $1 = "liberrors" ] ; then
 echo "\
 /*\n\
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.\n\
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.\n\
  * Use is subject to license terms.\n\
  */\n\
 \n\
@@ -95,6 +95,22 @@
 static const int _topo_nproperrstrs =\n\
     sizeof (_topo_properrstrs) / sizeof (_topo_properrstrs[0]);"
 
+elif [ $1 = "methoderrors" ] ; then
+
+echo "\
+\n\
+static const char *const _topo_methoderrstrs[] = {"
+
+pattern='^[ ]*ETOPO_METHOD_[A-Z0-9_]*.*\* \(.*\) \*.*'
+replace='	"\1",'
+
+echo "$input" | sed -n "s/$pattern/$replace/p" || exit 1
+
+echo "\
+};\n\
+\n\
+static const int _topo_nmethoderrstrs =\n\
+    sizeof (_topo_methoderrstrs) / sizeof (_topo_methoderrstrs[0]);"
 else
 
 echo "\
@@ -144,6 +160,9 @@
 	else if (err >= ETOPO_PROP_UNKNOWN && (err - ETOPO_PROP_UNKNOWN) <
 	    _topo_nproperrstrs)
 		s = _topo_properrstrs[err - ETOPO_PROP_UNKNOWN];
+	else if (err >= ETOPO_METHOD_UNKNOWN && (err - ETOPO_METHOD_UNKNOWN) <
+	    _topo_nmethoderrstrs)
+		s = _topo_methoderrstrs[err - ETOPO_METHOD_UNKNOWN];
 	else
 		s = _topo_errstrs[0];
 
--- a/usr/src/lib/fm/topo/libtopo/common/topo_error.h	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_error.h	Mon Feb 19 20:47:33 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -85,9 +85,6 @@
     ETOPO_FMRI_VERSION, /* invalid FMRI scheme version */
     ETOPO_FMRI_MALFORM,	/* malformed FMRI */
     ETOPO_NVL_INVAL,	/* invalid nvlist function argument */
-    ETOPO_METHOD_INVAL,	/* invalid method registration */
-    ETOPO_METHOD_NOTSUP, /* method not supported */
-    ETOPO_METHOD_FAIL,	/* method failed */
     ETOPO_FILE_NOENT,	/* no topology file found */
     ETOPO_PRSR_BADGRP,	/* unrecognized grouping */
     ETOPO_PRSR_BADNUM,	/* unable to interpret attribute numerically */
--- a/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c	Mon Feb 19 20:47:33 2007 -0800
@@ -232,8 +232,8 @@
 int
 topo_fmri_unusable(topo_hdl_t *thp, nvlist_t *fmri, int *err)
 {
-	int rc;
 	char *scheme;
+	uint32_t unusable = 0;
 	nvlist_t *out = NULL;
 	tnode_t *rnode;
 
@@ -245,11 +245,14 @@
 		return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
 		    TOPO_METH_UNUSABLE, out));
 
-	if ((rc = topo_method_invoke(rnode, TOPO_METH_UNUSABLE,
-	    TOPO_METH_UNUSABLE_VERSION, fmri, &out, err)) < 0)
+	if (topo_method_invoke(rnode, TOPO_METH_UNUSABLE,
+	    TOPO_METH_UNUSABLE_VERSION, fmri, &out, err) < 0)
 		return (set_error(thp, *err, err, TOPO_METH_UNUSABLE, out));
 
-	return (rc);
+	(void) nvlist_lookup_uint32(out, TOPO_METH_UNUSABLE_RET, &unusable);
+	nvlist_free(out);
+
+	return (unusable);
 }
 
 int
--- a/usr/src/lib/fm/topo/libtopo/common/topo_method.h	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.h	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -42,8 +42,6 @@
 #define	TOPO_METH_NVL2STR		"topo_nvl2str"
 #define	TOPO_METH_STR2NVL		"topo_str2nvl"
 #define	TOPO_METH_CONTAINS		"topo_contains"
-#define	TOPO_METH_UNUSABLE		"topo_unusable"
-#define	TOPO_METH_EXPAND		"topo_expand"
 #define	TOPO_METH_COMPARE		"topo_compare"
 
 #define	TOPO_METH_FMRI_VERSION			0
@@ -52,8 +50,6 @@
 #define	TOPO_METH_NVL2STR_VERSION		0
 #define	TOPO_METH_STR2NVL_VERSION		0
 #define	TOPO_METH_CONTAINS_VERSION		0
-#define	TOPO_METH_UNUSABLE_VERSION		0
-#define	TOPO_METH_EXPAND_VERSION		0
 #define	TOPO_METH_COMPARE_VERSION		0
 
 #define	TOPO_METH_ASRU_COMPUTE_DESC		"Dynamic ASRU constructor"
@@ -62,8 +58,6 @@
 #define	TOPO_METH_NVL2STR_DESC			"FMRI to string"
 #define	TOPO_METH_STR2NVL_DESC			"string to FMRI"
 #define	TOPO_METH_CONTAINS_DESC			"FMRI contains sub-FMRI"
-#define	TOPO_METH_UNUSABLE_DESC			"FMRI is unusable"
-#define	TOPO_METH_EXPAND_DESC			"expand FMRI"
 #define	TOPO_METH_COMPARE_DESC			"compare two FMRIs"
 
 #define	TOPO_METH_FMRI_ARG_NAME		"child-name"
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.h	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.h	Mon Feb 19 20:47:33 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -126,6 +126,17 @@
 #define	TOPO_METH_PRESENT_VERSION	TOPO_METH_PRESENT_VERSION0
 #define	TOPO_METH_PRESENT_RET		"present-ret"
 
+#define	TOPO_METH_UNUSABLE		"topo_unusable"
+#define	TOPO_METH_UNUSABLE_DESC		"FMRI is unusable"
+#define	TOPO_METH_UNUSABLE_VERSION0	0
+#define	TOPO_METH_UNUSABLE_VERSION	TOPO_METH_UNUSABLE_VERSION0
+#define	TOPO_METH_UNUSABLE_RET		"unusable-ret"
+
+#define	TOPO_METH_EXPAND		"topo_expand"
+#define	TOPO_METH_EXPAND_DESC		"expand FMRI"
+#define	TOPO_METH_EXPAND_VERSION0	0
+#define	TOPO_METH_EXPAND_VERSION	TOPO_METH_EXPAND_VERSION0
+
 #define	TOPO_METH_ASRU_COMPUTE		"topo_asru_compute"
 #define	TOPO_METH_ASRU_COMPUTE_VERSION	0
 #define	TOPO_METH_ASRU_COMPUTE_DESC	"Dynamic ASRU constructor"
--- a/usr/src/lib/fm/topo/modules/sun4/chip/Makefile.chip	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/chip/Makefile.chip	Mon Feb 19 20:47:33 2007 -0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -27,7 +27,7 @@
 MODULE = chip
 CLASS = arch
 SUN4DIR = ../../sun4/$(MODULE)
-MODULESRCS = chip_$(ARCH).c
+MODULESRCS = $($(ARCH)_SRCS)
 
 include ../../Makefile.plugin
 
--- a/usr/src/lib/fm/topo/modules/sun4u/chip/Makefile	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4u/chip/Makefile	Mon Feb 19 20:47:33 2007 -0800
@@ -19,13 +19,15 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
 
 ARCH = sun4u
 
+sun4u_SRCS = chip_sun4u.c
+
 include ../../sun4/chip/Makefile.chip
 
 LDLIBS += -lkstat
--- a/usr/src/lib/fm/topo/modules/sun4v/chip/Makefile	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/chip/Makefile	Mon Feb 19 20:47:33 2007 -0800
@@ -19,15 +19,26 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
 
 ARCH = sun4v
+PRIDIR=../platform-cpu
 
-INCDIRS = $(ROOT)/usr/platform/sun4v/include
+sun4v_SRCS = chip_sun4v.c cpu_mdesc.c
+
+INCDIRS = $(ROOT)/usr/platform/sun4v/include \
+		$(PRIDIR)
 
 include ../../sun4/chip/Makefile.chip
 
 LDLIBS += -lumem -lmdesc -lldom
+
+%.o: $(PRIDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
+%.ln: $(PRIDIR)/%.c
+	$(LINT.c) -c $<
--- a/usr/src/lib/fm/topo/modules/sun4v/chip/chip_sun4v.c	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/chip/chip_sun4v.c	Mon Feb 19 20:47:33 2007 -0800
@@ -27,10 +27,9 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <strings.h>
 #include <sys/types.h>
-#include <sys/mdesc.h>
-#include <sys/fm/ldom.h>
 #include <fm/topo_mod.h>
 #include <sys/fm/protocol.h>
 
@@ -40,7 +39,7 @@
 #include <fcntl.h>
 #include <umem.h>
 
-#include <stdlib.h>
+#include <cpu_mdesc.h>
 
 
 /*
@@ -53,32 +52,10 @@
 #define	CPU_NODE_NAME	"cpu"
 #define	CHIP_NODE_NAME	"chip"
 
-#define	MD_STR_LEN		32
-#define	MD_STR_CPU		"cpu"
-#define	MD_STR_COMPONENT	"component"
-#define	MD_STR_TYPE		"type"
-#define	MD_STR_PROCESSOR	"processor"
-#define	MD_STR_STRAND		"strand"
-#define	MD_STR_SERIAL		"serial_number"
-
-typedef struct md_cpumap {
-	uint32_t cpumap_id;		/* virtual cpuid */
-	uint32_t cpumap_pid;		/* physical cpuid */
-	uint64_t cpumap_serialno;	/* cpu serial number */
-} md_cpumap_t;
-
-typedef struct chip {
-	uint64_t *chip_serials;		/* List of cpu serial numbers */
-	md_cpumap_t *chip_cpus;		/* List of cpu maps */
-	uint32_t chip_ncpus;		/* size */
-} chip_t;
-
-
 /* Forward declaration */
 static int chip_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
     topo_instance_t, void *, void *);
 static void chip_release(topo_mod_t *, tnode_t *);
-static int cpu_mdesc_init(topo_mod_t *mod, chip_t *chip);
 
 
 static const topo_modops_t chip_ops =
@@ -94,43 +71,33 @@
 	1
 };
 
-static void *
-chip_alloc(size_t size)
-{
-	return (umem_alloc(size, UMEM_DEFAULT));
-}
-
-static void
-chip_free(void *data, size_t size)
-{
-	umem_free(data, size);
-}
-
 int
 _topo_init(topo_mod_t *mod)
 {
-	chip_t *chip;
+	md_info_t *chip;
 
 	if (getenv("TOPOCHIPDBG"))
 		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing chip enumerator\n");
 
-	if ((chip = topo_mod_zalloc(mod, sizeof (chip_t))) == NULL)
+	if ((chip = topo_mod_zalloc(mod, sizeof (md_info_t))) == NULL)
 		return (-1);
 
 	if (cpu_mdesc_init(mod, chip) != 0) {
 		topo_mod_dprintf(mod, "failed to get cpus from the PRI/MD\n");
-		topo_mod_free(mod, chip, sizeof (chip_t));
+		topo_mod_free(mod, chip, sizeof (md_info_t));
 		return (-1);
 	}
 
+	topo_mod_setspecific(mod, (void *)chip);
+
 	if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register hc: "
 		    "%s\n", topo_mod_errmsg(mod));
-		topo_mod_free(mod, chip, sizeof (chip_t));
+		cpu_mdesc_fini(mod, chip);
+		topo_mod_free(mod, chip, sizeof (md_info_t));
 		return (-1);
 	}
-	topo_mod_setspecific(mod, (void *)chip);
 
 	topo_mod_dprintf(mod, "chip enumerator inited\n");
 
@@ -140,22 +107,15 @@
 void
 _topo_fini(topo_mod_t *mod)
 {
-	chip_t *chip;
+	md_info_t *chip;
 
-	chip = (chip_t *)topo_mod_getspecific(mod);
+	chip = (md_info_t *)topo_mod_getspecific(mod);
 
-	if (chip->chip_serials != NULL)
-		topo_mod_free(mod, chip->chip_serials,
-			chip->chip_ncpus * sizeof (uint64_t));
+	cpu_mdesc_fini(mod, chip);
 
-	if (chip->chip_cpus != NULL)
-		topo_mod_free(mod, chip->chip_cpus,
-			chip->chip_ncpus * sizeof (md_cpumap_t));
-
-	topo_mod_free(mod, chip, sizeof (chip_t));
+	topo_mod_free(mod, chip, sizeof (md_info_t));
 
 	topo_mod_unregister(mod);
-
 }
 
 static tnode_t *
@@ -171,17 +131,23 @@
 
 	if (topo_mod_nvalloc(mod, &auth, NV_UNIQUE_NAME) == 0) {
 		if (topo_prop_get_string(parent, FM_FMRI_AUTHORITY,
-		    FM_FMRI_AUTH_PRODUCT, &prod, &err) == 0)
-		    (void) nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT,
-			    prod);
+			FM_FMRI_AUTH_PRODUCT, &prod, &err) == 0) {
+			(void) nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT,
+						prod);
+			topo_mod_strfree(mod, prod);
+		}
 		if (topo_prop_get_string(parent, FM_FMRI_AUTHORITY,
-			FM_FMRI_AUTH_SERVER, &server, &err) == 0)
+			FM_FMRI_AUTH_SERVER, &server, &err) == 0) {
 			(void) nvlist_add_string(auth, FM_FMRI_AUTH_SERVER,
-			    server);
+						server);
+			topo_mod_strfree(mod, server);
+		}
 		if (topo_prop_get_string(parent, FM_FMRI_AUTHORITY,
-		    FM_FMRI_AUTH_CHASSIS, &csn, &err) == 0)
+			FM_FMRI_AUTH_CHASSIS, &csn, &err) == 0) {
 			(void) nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS,
-			    csn);
+						csn);
+			topo_mod_strfree(mod, csn);
+		}
 	}
 
 
@@ -224,203 +190,6 @@
 	return (ntn);
 }
 
-static int
-cpu_n1_mdesc_init(topo_mod_t *mod, md_t *mdp, chip_t *chip)
-{
-	mde_cookie_t *listp;
-	md_cpumap_t *mcmp;
-	int i, num_nodes, idx;
-
-	num_nodes = md_node_count(mdp);
-	listp = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * num_nodes);
-
-	chip->chip_ncpus = md_scan_dag(mdp,
-					MDE_INVAL_ELEM_COOKIE,
-					md_find_name(mdp, "cpu"),
-					md_find_name(mdp, "fwd"),
-					listp);
-	topo_mod_dprintf(mod, "Found %d cpus\n", chip->chip_ncpus);
-
-	chip->chip_cpus = topo_mod_zalloc(mod, chip->chip_ncpus *
-	    sizeof (md_cpumap_t));
-	chip->chip_serials = topo_mod_zalloc(mod, chip->chip_ncpus *
-	    sizeof (uint64_t));
-
-	for (idx = 0, mcmp = chip->chip_cpus;
-	    idx < chip->chip_ncpus;
-	    idx++, mcmp++) {
-		uint64_t tl;
-
-		if (md_get_prop_val(mdp, listp[idx], "id", &tl) < 0)
-			tl = (uint64_t)-1; /* invalid value */
-		mcmp->cpumap_id = tl;
-
-		if (md_get_prop_val(mdp, listp[idx], "pid", &tl) < 0)
-			tl = mcmp->cpumap_id;
-		mcmp->cpumap_pid = tl;
-
-		if (md_get_prop_val(mdp, listp[idx], "serial#",
-		    &mcmp->cpumap_serialno) < 0)
-			mcmp->cpumap_serialno = 0;
-
-		/* unique serial number */
-		for (i = 0; i < chip->chip_ncpus &&
-		    chip->chip_serials[i] != 0; i++) {
-			if (mcmp->cpumap_serialno == chip->chip_serials[i]) {
-				break;
-			}
-		}
-		if (i < chip->chip_ncpus && chip->chip_serials[i] == 0) {
-			chip->chip_serials[i] = mcmp->cpumap_serialno;
-			topo_mod_dprintf(mod, "chip[%d] serial is %llx\n", i,
-				chip->chip_serials[i]);
-		}
-	}
-
-	topo_mod_free(mod, listp, sizeof (mde_cookie_t) * num_nodes);
-
-	return (0);
-}
-
-static int
-cpu_n2_mdesc_init(topo_mod_t *mod, md_t *mdp, chip_t *chip)
-{
-	mde_cookie_t *list1p, *list2p;
-	md_cpumap_t *mcmp;
-	int i, j, cnt;
-	int nnode, ncomp, nproc, ncpu;
-	char *str = NULL;
-	uint64_t sn;
-	uint64_t tl;
-
-	nnode = md_node_count(mdp);
-	list1p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode);
-
-	/* Count the number of processors and strands */
-	ncomp = md_scan_dag(mdp,
-			MDE_INVAL_ELEM_COOKIE,
-			md_find_name(mdp, MD_STR_COMPONENT),
-			md_find_name(mdp, "fwd"),
-			list1p);
-	if (ncomp <= 0) {
-		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
-		return (-1);
-	}
-	for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) {
-		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 &&
-		    str != NULL && strcmp(str, MD_STR_PROCESSOR) == 0) {
-			nproc++;
-		}
-		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 &&
-		    str != NULL && strcmp(str, MD_STR_STRAND) == 0) {
-			ncpu++;
-		}
-	}
-	topo_mod_dprintf(mod, "Found %d procs and %d strands\n", nproc, ncpu);
-	if (ncpu <= 0 || nproc <= 0) {
-		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
-		return (-1);
-	}
-
-	/* Alloc processor and strand entries */
-	list2p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * 2 * ncpu);
-	chip->chip_ncpus = ncpu;
-	chip->chip_cpus = topo_mod_zalloc(mod, chip->chip_ncpus *
-					sizeof (md_cpumap_t));
-	chip->chip_serials = topo_mod_zalloc(mod, chip->chip_ncpus *
-					sizeof (uint64_t));
-
-	/* Visit each processor node */
-	mcmp = chip->chip_cpus;
-	for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) {
-		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) < 0 ||
-		    str ==  NULL || strcmp(str, MD_STR_PROCESSOR))
-			continue;
-		if (md_get_prop_val(mdp, list1p[i], MD_STR_SERIAL, &sn) < 0) {
-			topo_mod_dprintf(mod,
-				"Failed to get the serial number of proc[%d]",
-				nproc);
-			continue;
-		}
-		chip->chip_serials[nproc] = sn;
-		topo_mod_dprintf(mod, "proc %d : sn=%llx\n", nproc, sn);
-		nproc++;
-
-		/* Get all the strands below this proc */
-		cnt = md_scan_dag(mdp,
-				list1p[i],
-				md_find_name(mdp, MD_STR_COMPONENT),
-				md_find_name(mdp, "fwd"),
-				list2p);
-		if (cnt <= 0) {
-			continue;
-		}
-		for (j = 0; j < cnt && ncpu < chip->chip_ncpus; j++) {
-			/* Consider only the strand nodes */
-			if (md_get_prop_str(mdp, list2p[j], MD_STR_TYPE, &str)
-			    < 0 || str == NULL || strcmp(str, MD_STR_STRAND))
-				continue;
-
-			if (md_get_prop_val(mdp, list2p[j], "id", &tl) < 0)
-				tl = (uint64_t)-1; /* invalid value */
-			mcmp->cpumap_id = tl;
-
-			if (md_get_prop_val(mdp, list2p[j], "pid", &tl) < 0)
-				tl = mcmp->cpumap_id;
-			mcmp->cpumap_pid = tl;
-
-			mcmp->cpumap_serialno = sn;
-			mcmp++;
-			ncpu++;
-		}
-	}
-
-	topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
-	topo_mod_free(mod, list2p, sizeof (mde_cookie_t) * 2*chip->chip_ncpus);
-
-	return (0);
-}
-
-static int
-cpu_mdesc_init(topo_mod_t *mod, chip_t *chip)
-{
-	int rc;
-	md_t *mdp;
-	ssize_t bufsiz = 0;
-	uint64_t *bufp;
-	ldom_hdl_t *lhp;
-
-	lhp = ldom_init(chip_alloc, chip_free);
-	if ((bufsiz = ldom_get_core_md(lhp, &bufp)) <= 0) {
-		return (-1);
-	}
-
-	if ((mdp = md_init_intern(bufp, chip_alloc, chip_free)) == NULL ||
-	    md_node_count(mdp) <= 0) {
-		chip_free(bufp, (size_t)bufsiz);
-		ldom_fini(lhp);
-		return (-1);
-	}
-
-	/*
-	 * N1 MD contains cpu nodes while N2 MD contains component nodes
-	 */
-	if (md_find_name(mdp, MD_STR_COMPONENT) != MDE_INVAL_STR_COOKIE) {
-		rc = cpu_n2_mdesc_init(mod, mdp, chip);
-	} else if (md_find_name(mdp, MD_STR_CPU) != MDE_INVAL_STR_COOKIE) {
-		rc =  cpu_n1_mdesc_init(mod, mdp, chip);
-	} else {
-		topo_mod_dprintf(mod, "Unsupported MD/PRI\n");
-		rc = -1;
-	}
-
-	chip_free(bufp, (size_t)bufsiz);
-	(void) md_fini(mdp);
-	ldom_fini(lhp);
-
-	return (rc);
-}
-
 static nvlist_t *
 cpu_fmri_create(topo_mod_t *mod, uint32_t cpuid, char *serial, uint8_t cpumask)
 {
@@ -446,7 +215,7 @@
 
 /*ARGSUSED*/
 static int
-cpu_create(topo_mod_t *mod, tnode_t *rnode, const char *name, chip_t *chip,
+cpu_create(topo_mod_t *mod, tnode_t *rnode, const char *name, md_info_t *chip,
 		int chipidx)
 {
 	int i;
@@ -458,20 +227,22 @@
 	char sbuf[32];
 	tnode_t *cnode;
 	nvlist_t *asru;
+	md_cpumap_t *mcmp;
+	md_proc_t *procp;
 
 	topo_mod_dprintf(mod, "enumerating cpus\n");
 
 	/*
 	 * find the min/max id of cpus per this cmp and create a cpu range
 	 */
-	for (i = 0; i < chip->chip_ncpus; i++) {
-		if (chip->chip_cpus[i].cpumap_serialno !=
-		    chip->chip_serials[chipidx])
+	procp = chip->procs + chipidx;
+	for (i = 0, mcmp = chip->cpus; i < chip->ncpus; i++, mcmp++) {
+		if (mcmp->cpumap_serialno != procp->serialno)
 			continue;
-		if ((min < 0) || (chip->chip_cpus[i].cpumap_pid < min))
-			min = chip->chip_cpus[i].cpumap_pid;
-		if ((max < 0) || (chip->chip_cpus[i].cpumap_pid > max))
-			max = chip->chip_cpus[i].cpumap_pid;
+		if ((min < 0) || (mcmp->cpumap_pid < min))
+			min = mcmp->cpumap_pid;
+		if ((max < 0) || (mcmp->cpumap_pid > max))
+			max = mcmp->cpumap_pid;
 	}
 	if (min < 0 || max < 0)
 		return (-1);
@@ -482,21 +253,19 @@
 		return (-1);
 	}
 
-	(void) snprintf(sbuf, sizeof (sbuf), "%llx",
-			chip->chip_serials[chipidx]);
+	(void) snprintf(sbuf, sizeof (sbuf), "%llx", procp->serialno);
 
 	/*
 	 * Create the cpu[i] nodes of a given cmp chipidx
 	 */
-	for (i = 0; i < chip->chip_ncpus; i++) {
+	for (i = 0, mcmp = chip->cpus; i < chip->ncpus; i++, mcmp++) {
 
-		if (chip->chip_cpus[i].cpumap_serialno !=
-		    chip->chip_serials[chipidx]) {
+		if (mcmp->cpumap_serialno != procp->serialno) {
 			continue;
 		}
 
 		/* physical cpuid */
-		pid = chip->chip_cpus[i].cpumap_pid;
+		pid = mcmp->cpumap_pid;
 		cnode = chip_tnode_create(mod, rnode, name,
 					(topo_instance_t)pid, sbuf,
 					NULL, NULL, NULL);
@@ -525,7 +294,7 @@
 /*ARGSUSED*/
 static int
 chip_create(topo_mod_t *mod, tnode_t *rnode, const char *name,
-    topo_instance_t min, topo_instance_t max, chip_t *chip)
+    topo_instance_t min, topo_instance_t max, md_info_t *chip)
 {
 	int nerr = 0;
 	int err;
@@ -534,11 +303,13 @@
 	tnode_t *cnode;
 	nvlist_t *fru = NULL;
 	char *label = NULL;
+	md_proc_t *procp;
 
 	topo_mod_dprintf(mod, "enumerating cmp chip\n");
 
-	for (chipidx = 0; chipidx < chip->chip_ncpus &&
-			chip->chip_serials[chipidx] != 0; chipidx++);
+	/* Create the range of chip nodes */
+	for (chipidx = 0, procp = chip->procs; chipidx < chip->nprocs &&
+			procp->serialno != 0; chipidx++, procp++);
 	topo_node_range_destroy(rnode, name);
 	if (topo_node_range_create(mod, rnode, name, 0, chipidx+1) < 0) {
 		topo_mod_dprintf(mod, "failed to create chip range[0,%d]: %s\n",
@@ -550,11 +321,14 @@
 	 * Create the chip[i] nodes, one for each CMP chip uniquely identified
 	 * by the serial number.
 	 */
-	for (chipidx = 0; chipidx < chip->chip_ncpus &&
-			chip->chip_serials[chipidx] != 0; chipidx++) {
+	for (chipidx = 0, procp = chip->procs; chipidx < chip->nprocs;
+		chipidx++, procp++) {
+		if (procp->serialno == 0) {
+			continue;
+		}
 
 		(void) snprintf(sbuf, sizeof (sbuf), "%llx",
-				chip->chip_serials[chipidx]);
+				procp->serialno);
 
 		topo_mod_dprintf(mod, "enumerating chip [%s]\n", sbuf);
 
@@ -586,7 +360,7 @@
 chip_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
     topo_instance_t min, topo_instance_t max, void *arg, void *notused)
 {
-	chip_t *chip = (chip_t *)arg;
+	md_info_t *chip = (md_info_t *)arg;
 
 	if (strcmp(name, CHIP_NODE_NAME) == 0)
 		return (chip_create(mod, rnode, name, min, max, chip));
--- a/usr/src/lib/fm/topo/modules/sun4v/motherboard/motherboard.c	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/motherboard/motherboard.c	Mon Feb 19 20:47:33 2007 -0800
@@ -119,8 +119,7 @@
 }
 
 static int
-mb_get_pri_info(topo_mod_t *mod, ldom_hdl_t *lhp,
-	char **serialp, char **partp, char **csnp)
+mb_get_pri_info(topo_mod_t *mod, char **serialp, char **partp, char **csnp)
 {
 	char isa[MAXNAMELEN];
 	md_t *mdp;
@@ -130,26 +129,35 @@
 	int  nfrus, num_nodes, i;
 	char *pstr = NULL;
 	char *sn, *pn, *dn, *csn;
+	ldom_hdl_t *lhp;
+
+	lhp = ldom_init(mb_topo_alloc, mb_topo_free);
+	if (lhp == NULL) {
+		topo_mod_dprintf(mod, "ldom_init failed\n");
+		return (-1);
+	}
 
 	(void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
-
 	if (strcmp(isa, "sun4v") != 0) {
 		topo_mod_dprintf(mod, "not sun4v architecture%s\n",
 			isa);
+		ldom_fini(lhp);
 		return (-1);
 	}
 
 	if ((bufsize = ldom_get_core_md(lhp, &bufp)) < 1) {
 		topo_mod_dprintf(mod, "ldom_get_core_md error, bufsize=%d\n",
 			bufsize);
+		ldom_fini(lhp);
 		return (-1);
 	}
 	topo_mod_dprintf(mod, "pri bufsize=%d\n", bufsize);
 
 	if ((mdp = md_init_intern(bufp, mb_topo_alloc, mb_topo_free)) == NULL ||
 	    (num_nodes = md_node_count(mdp)) < 1) {
-		mb_topo_free(bufp, bufsize);
 		topo_mod_dprintf(mod, "md_init_intern error\n");
+		mb_topo_free(bufp, (size_t)bufsize);
+		ldom_fini(lhp);
 		return (-1);
 	}
 	topo_mod_dprintf(mod, "num_nodes=%d\n", num_nodes);
@@ -157,6 +165,9 @@
 	if ((listp = (mde_cookie_t *)mb_topo_alloc(
 		sizeof (mde_cookie_t) * num_nodes)) == NULL) {
 		topo_mod_dprintf(mod, "alloc listp error\n");
+		mb_topo_free(bufp, (size_t)bufsize);
+		(void) md_fini(mdp);
+		ldom_fini(lhp);
 		return (-1);
 	}
 
@@ -165,6 +176,10 @@
 			md_find_name(mdp, "fwd"), listp);
 	if (nfrus <= 0) {
 		topo_mod_dprintf(mod, "error: nfrus=%d\n", nfrus);
+		mb_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
+		mb_topo_free(bufp, (size_t)bufsize);
+		(void) md_fini(mdp);
+		ldom_fini(lhp);
 		return (-1);
 	}
 	topo_mod_dprintf(mod, "nfrus=%d\n", nfrus);
@@ -192,17 +207,19 @@
 	}
 
 	*serialp = topo_mod_strdup(mod, sn);
-	*partp = topo_mod_alloc(mod, (strlen(dn)
-			+ strlen(pn) + 1));
-	(void) strcpy(*partp, pn);
-	if (dn != NULL)
-		(void) strcat(*partp, dn);
+
+	i = (pn ? strlen(pn) : 0) + (dn ? strlen(dn) : 0) + 1;
+	pstr = mb_topo_alloc(i);
+	(void) snprintf(pstr, i, "%s%s", pn ? pn : "", dn ? dn : "");
+	*partp = topo_mod_strdup(mod, pstr);
+	mb_topo_free(pstr, i);
 
 	*csnp = topo_mod_strdup(mod, csn);
 
 	mb_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
 	mb_topo_free(bufp, (size_t)bufsize);
 	(void) md_fini(mdp);
+	ldom_fini(lhp);
 
 	return (0);
 }
@@ -249,13 +266,10 @@
 	tnode_t *ntn;
 	char *serial = NULL, *part = NULL;
 	char *csn = NULL, *pstr = NULL;
-	ldom_hdl_t *motherboard_lhp;
 	nvlist_t *auth = topo_mod_auth(mod, parent);
 
-	motherboard_lhp = ldom_init(mb_topo_alloc, mb_topo_free);
-
 	/* Get Chassis ID, MB Serial Number and Part Number from PRI */
-	(void) mb_get_pri_info(mod, motherboard_lhp, &serial, &part, &csn);
+	(void) mb_get_pri_info(mod, &serial, &part, &csn);
 
 	if (nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &pstr) != 0 &&
 	    csn != NULL)
@@ -267,12 +281,12 @@
 	topo_mod_strfree(mod, serial);
 	topo_mod_strfree(mod, part);
 	topo_mod_strfree(mod, csn);
-	ldom_fini(motherboard_lhp);
 
 	if (fmri == NULL) {
 		topo_mod_dprintf(mod,
 		    "Unable to make nvlist for %s bind: %s.\n",
 		    name, topo_mod_errmsg(mod));
+		nvlist_free(auth);
 		return (NULL);
 	}
 
@@ -283,6 +297,7 @@
 		    topo_node_name(parent), topo_node_instance(parent),
 		    name, i,
 		    topo_strerror(topo_mod_errno(mod)));
+		nvlist_free(auth);
 		nvlist_free(fmri);
 		return (NULL);
 	}
--- a/usr/src/lib/fm/topo/modules/sun4v/platform-cpu/Makefile	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/platform-cpu/Makefile	Mon Feb 19 20:47:33 2007 -0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -28,7 +28,7 @@
 ARCH = sun4v
 CLASS = arch
 
-MODULESRCS = cpu.c
+MODULESRCS = cpu.c cpu_mdesc.c
 
 include ../../Makefile.plugin
 
--- a/usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu.c	Mon Feb 19 05:28:47 2007 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu.c	Mon Feb 19 20:47:33 2007 -0800
@@ -26,49 +26,36 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include <stdio.h>
 #include <strings.h>
 #include <umem.h>
-#include <sys/types.h>
-#include <sys/mdesc.h>
+#include <fm/topo_mod.h>
 #include <sys/fm/ldom.h>
-#include <fm/topo_mod.h>
 #include <sys/fm/protocol.h>
 
+#include <cpu_mdesc.h>
+
 /*
- * Enumerates the cpu strands in a system. For each strand found, the
- * necessary cpu-schemed nodes are constructed underneath.
+ * This enumerator creates cpu-schemed nodes for each strand found in the
+ * sun4v Physical Rource Inventory (PRI).
+ * Each node export three methods present(), expand() and unusable().
+ *
  */
 
 #define	PLATFORM_CPU_NAME	"platform-cpu"
 #define	PLATFORM_CPU_VERSION	TOPO_VERSION
 #define	CPU_NODE_NAME		"cpu"
 
-#define	MD_STR_CPU		"cpu"
-#define	MD_STR_COMPONENT	"component"
-#define	MD_STR_TYPE		"type"
-#define	MD_STR_PROCESSOR	"processor"
-#define	MD_STR_STRAND		"strand"
-#define	MD_STR_SERIAL		"serial_number"
-
-typedef struct md_cpumap {
-	uint32_t cpumap_id;		/* virtual cpuid */
-	uint32_t cpumap_pid;		/* physical cpuid */
-	uint64_t cpumap_serialno;	/* cpu serial number */
-} md_cpumap_t;
-
-typedef struct chip {
-	md_cpumap_t *chip_cpus;		/* List of cpu maps */
-	uint32_t chip_ncpus;		/* size */
-} chip_t;
-
 
 /* Forward declaration */
 static int cpu_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
     topo_instance_t, void *, void *);
 static void cpu_release(topo_mod_t *, tnode_t *);
-static int cpu_mdesc_init(topo_mod_t *mod, chip_t *chip);
-
+static int cpu_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+    nvlist_t **);
+static int cpu_expand(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+    nvlist_t **);
+static int cpu_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+    nvlist_t **);
 
 static const topo_modops_t cpu_ops =
 	{ cpu_enum, cpu_release };
@@ -76,6 +63,15 @@
 	{ PLATFORM_CPU_NAME, FM_FMRI_SCHEME_CPU, PLATFORM_CPU_VERSION,
 		&cpu_ops };
 
+static const topo_method_t cpu_methods[] = {
+	{ TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC,
+	    TOPO_METH_PRESENT_VERSION, TOPO_STABILITY_INTERNAL, cpu_present },
+	{ TOPO_METH_EXPAND, TOPO_METH_EXPAND_DESC,
+	    TOPO_METH_EXPAND_VERSION, TOPO_STABILITY_INTERNAL, cpu_expand },
+	{ TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC,
+	    TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL, cpu_unusable },
+	{ NULL }
+};
 
 static void *
 cpu_alloc(size_t size)
@@ -92,29 +88,31 @@
 int
 _topo_init(topo_mod_t *mod)
 {
-	chip_t *chip;
+	md_info_t *chip;
 
 	if (getenv("TOPOPLATFORMCPUDBG"))
 		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing %s enumerator\n",
 			PLATFORM_CPU_NAME);
 
-	if ((chip = topo_mod_zalloc(mod, sizeof (chip_t))) == NULL)
+	if ((chip = topo_mod_zalloc(mod, sizeof (md_info_t))) == NULL)
 		return (-1);
 
 	if (cpu_mdesc_init(mod, chip) != 0) {
 		topo_mod_dprintf(mod, "failed to get cpus from the PRI/MD\n");
-		topo_mod_free(mod, chip, sizeof (chip_t));
+		topo_mod_free(mod, chip, sizeof (md_info_t));
 		return (-1);
 	}
 
+	topo_mod_setspecific(mod, (void *)chip);
+
 	if (topo_mod_register(mod, &cpu_info, TOPO_VERSION) != 0) {
-		topo_mod_dprintf(mod, "failed to register hc: "
-		    "%s\n", topo_mod_errmsg(mod));
-		topo_mod_free(mod, chip, sizeof (chip_t));
+		topo_mod_dprintf(mod, "failed to register %s: %s\n",
+				PLATFORM_CPU_NAME, topo_mod_errmsg(mod));
+		cpu_mdesc_fini(mod, chip);
+		topo_mod_free(mod, chip, sizeof (md_info_t));
 		return (-1);
 	}
-	topo_mod_setspecific(mod, (void *)chip);
 
 	topo_mod_dprintf(mod, "%s enumerator inited\n", PLATFORM_CPU_NAME);
 
@@ -124,196 +122,158 @@
 void
 _topo_fini(topo_mod_t *mod)
 {
-	chip_t *chip;
+	md_info_t *chip;
 
-	chip = (chip_t *)topo_mod_getspecific(mod);
+	chip = (md_info_t *)topo_mod_getspecific(mod);
 
-	if (chip->chip_cpus != NULL)
-		topo_mod_free(mod, chip->chip_cpus,
-			chip->chip_ncpus * sizeof (md_cpumap_t));
+	cpu_mdesc_fini(mod, chip);
 
-	topo_mod_free(mod, chip, sizeof (chip_t));
+	topo_mod_free(mod, chip, sizeof (md_info_t));
 
 	topo_mod_unregister(mod);
 
 }
 
+/*ARGSUSED*/
 static int
-cpu_n1_mdesc_init(topo_mod_t *mod, md_t *mdp, chip_t *chip)
+cpu_present(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
 {
-	mde_cookie_t *listp;
+	uint8_t version;
+	uint32_t cpuid;
+	uint64_t nvlserid;
+	uint32_t present = 0;
 	md_cpumap_t *mcmp;
-	int num_nodes, idx;
-
-	num_nodes = md_node_count(mdp);
-	listp = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * num_nodes);
-
-	chip->chip_ncpus = md_scan_dag(mdp,
-					MDE_INVAL_ELEM_COOKIE,
-					md_find_name(mdp, "cpu"),
-					md_find_name(mdp, "fwd"),
-					listp);
-	topo_mod_dprintf(mod, "Found %d cpus\n", chip->chip_ncpus);
+	md_info_t *chip = (md_info_t *)topo_mod_getspecific(mod);
 
-	chip->chip_cpus = topo_mod_zalloc(mod, chip->chip_ncpus *
-	    sizeof (md_cpumap_t));
-
-	for (idx = 0, mcmp = chip->chip_cpus;
-	    idx < chip->chip_ncpus;
-	    idx++, mcmp++) {
-		uint64_t tl;
-
-		if (md_get_prop_val(mdp, listp[idx], "id", &tl) < 0)
-			tl = (uint64_t)-1; /* invalid value */
-		mcmp->cpumap_id = tl;
-
-		if (md_get_prop_val(mdp, listp[idx], "pid", &tl) < 0)
-			tl = mcmp->cpumap_id;
-		mcmp->cpumap_pid = tl;
-
-		if (md_get_prop_val(mdp, listp[idx], "serial#",
-		    &mcmp->cpumap_serialno) < 0)
-			mcmp->cpumap_serialno = 0;
+	/*
+	 * Support only cpu scheme version 0
+	 */
+	if (nvlist_lookup_uint8(in, FM_VERSION, &version) != 0 ||
+	    version > CPU_SCHEME_VERSION0 ||
+	    nvlist_lookup_uint32(in, FM_FMRI_CPU_ID, &cpuid) != 0 ||
+	    nvlist_lookup_uint64(in, FM_FMRI_CPU_SERIAL_ID, &nvlserid) != 0) {
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
 	}
 
-	topo_mod_free(mod, listp, sizeof (mde_cookie_t) * num_nodes);
+	/* Find the cpuid entry */
+	if ((mcmp = cpu_find_cpumap(chip, cpuid)) != NULL) {
+		present = nvlserid == mcmp->cpumap_serialno;
+	}
+
+	/* return the present status */
+	if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) != 0)
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	if (nvlist_add_uint32(*out, TOPO_METH_PRESENT_RET, present) != 0) {
+		nvlist_free(*out);
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
 
 	return (0);
 }
 
+/*ARGSUSED*/
 static int
-cpu_n2_mdesc_init(topo_mod_t *mod, md_t *mdp, chip_t *chip)
+cpu_expand(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
 {
-	mde_cookie_t *list1p, *list2p;
+	int rc;
+	uint8_t version;
+	uint32_t cpuid;
+	uint64_t nvlserid;
 	md_cpumap_t *mcmp;
-	int i, j;
-	int nnode, ncomp, nproc, ncpu;
-	char *str = NULL;
-	uint64_t sn;
-
-	nnode = md_node_count(mdp);
-	list1p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode);
+	md_info_t *chip = (md_info_t *)topo_mod_getspecific(mod);
 
-	/* Count the number of strands */
-	ncomp = md_scan_dag(mdp,
-			MDE_INVAL_ELEM_COOKIE,
-			md_find_name(mdp, MD_STR_COMPONENT),
-			md_find_name(mdp, "fwd"),
-			list1p);
-	if (ncomp <= 0) {
-		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
-		return (-1);
-	}
-	for (i = 0, ncpu = 0; i < ncomp; i++) {
-		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 &&
-		    str && strcmp(str, MD_STR_STRAND) == 0) {
-			ncpu++;
-		}
-	}
-	topo_mod_dprintf(mod, "Found %d strands\n", ncpu);
-	if (ncpu == 0) {
-		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
-		return (-1);
+	if (nvlist_lookup_uint8(in, FM_VERSION, &version) != 0 ||
+	    version > FM_CPU_SCHEME_VERSION ||
+	    nvlist_lookup_uint32(in, FM_FMRI_CPU_ID, &cpuid) != 0) {
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
 	}
 
-	/* Alloc strand entries */
-	list2p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * 2 * ncpu);
-	chip->chip_ncpus = ncpu;
-	chip->chip_cpus = topo_mod_zalloc(mod, ncpu * sizeof (md_cpumap_t));
-
-	/* Visit each processor node */
-	mcmp = chip->chip_cpus;
-	for (i = 0, nproc = 0; i < ncomp; i++) {
-		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) < 0 ||
-		    str == NULL || strcmp(str, MD_STR_PROCESSOR))
-			continue;
-		if (md_get_prop_val(mdp, list1p[i], MD_STR_SERIAL, &sn) < 0) {
-			topo_mod_dprintf(mod,
-				"Failed to get the serial number of proc[%d]\n",
-				nproc);
-			continue;
+	if ((rc = nvlist_lookup_uint64(in, FM_FMRI_CPU_SERIAL_ID,
+	    &nvlserid)) != 0) {
+		if (rc != ENOENT) {
+			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
 		}
-		nproc++;
-
-		/* Get all the strands below this proc */
-		ncpu = md_scan_dag(mdp,
-				list1p[i],
-				md_find_name(mdp, MD_STR_COMPONENT),
-				md_find_name(mdp, "fwd"),
-				list2p);
-		topo_mod_dprintf(mod, "proc[%llx]: Found %d components\n",
-				sn, ncpu);
-		if (ncpu <= 0) {
-			continue;
+		/* Find the cpuid entry */
+		if ((mcmp = cpu_find_cpumap(chip, cpuid)) == NULL) {
+			return (-1);
 		}
-		for (j = 0; j < ncpu; j++) {
-			uint64_t tl;
-
-			/* Consider only the strand nodes */
-			if (md_get_prop_str(mdp, list2p[j], MD_STR_TYPE, &str)
-			    < 0 || str == NULL || strcmp(str, MD_STR_STRAND))
-				continue;
-
-			if (md_get_prop_val(mdp, list2p[j], "id", &tl) < 0)
-				tl = (uint64_t)-1; /* invalid value */
-			mcmp->cpumap_id = tl;
-
-			if (md_get_prop_val(mdp, list2p[j], "pid", &tl) < 0)
-				tl = mcmp->cpumap_id;
-			mcmp->cpumap_pid = tl;
-
-			mcmp->cpumap_serialno = sn;
-			mcmp++;
+		if ((rc = nvlist_add_uint64(in, FM_FMRI_CPU_SERIAL_ID,
+		    mcmp->cpumap_serialno)) != 0) {
+			return (topo_mod_seterrno(mod, rc));
 		}
 	}
+	topo_mod_dprintf(mod, "nvlserid=%llX\n", nvlserid);
+	if (mcmp != NULL &&
+	    mcmp->cpumap_chipidx >= 0 &&
+	    mcmp->cpumap_chipidx < chip->nprocs &&
+	    chip->procs &&
+	    chip->procs[mcmp->cpumap_chipidx].fru) {
+		int len;
+		char *str;
+		md_fru_t *frup = chip->procs[mcmp->cpumap_chipidx].fru;
 
-	topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
-	topo_mod_free(mod, list2p, sizeof (mde_cookie_t) * 2*chip->chip_ncpus);
+		/* part number + dash number */
+		len = (frup->part ? strlen(frup->part) : 0) +
+			(frup->dash ? strlen(frup->dash) : 0) + 1;
+		str = cpu_alloc(len);
+		(void) snprintf(str, len, "%s%s",
+				frup->part ? frup->part : MD_STR_BLANK,
+				frup->dash ? frup->dash : MD_STR_BLANK);
+		(void) nvlist_add_string(in, FM_FMRI_HC_PART, str);
+		cpu_free(str, len);
+
+		/* fru name */
+		(void) nvlist_add_string(in, FM_FMRI_CPU_CPUFRU,
+				frup->nac ? frup->nac : MD_STR_BLANK);
+
+		/* fru serial */
+		in->nvl_nvflag = NV_UNIQUE_NAME_TYPE;
+		(void) nvlist_add_string(in, FM_FMRI_HC_SERIAL_ID,
+			frup->serial ? frup->serial : MD_STR_BLANK);
+	}
 
 	return (0);
 }
 
+/*ARGSUSED*/
 static int
-cpu_mdesc_init(topo_mod_t *mod, chip_t *chip)
+cpu_unusable(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
+    nvlist_t *in, nvlist_t **out)
 {
 	int rc = -1;
-	md_t *mdp;
-	ssize_t bufsiz = 0;
-	uint64_t *bufp;
+	uint8_t version;
+	int status;
+	uint32_t cpuid;
 	ldom_hdl_t *lhp;
 
-	/* get the PRI/MD */
-	lhp = ldom_init(cpu_alloc, cpu_free);
-	if ((lhp == NULL) || (bufsiz = ldom_get_core_md(lhp, &bufp)) <= 0) {
-		topo_mod_dprintf(mod, "failed to get the PRI/MD\n");
-		return (-1);
+	if (nvlist_lookup_uint8(in, FM_VERSION, &version) != 0 ||
+	    version > FM_CPU_SCHEME_VERSION ||
+	    nvlist_lookup_uint32(in, FM_FMRI_CPU_ID, &cpuid) != 0) {
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
 	}
 
-	if ((mdp = md_init_intern(bufp, cpu_alloc, cpu_free)) == NULL ||
-	    md_node_count(mdp) <= 0) {
-		cpu_free(bufp, (size_t)bufsiz);
-		ldom_fini(lhp);
-		return (-1);
+	lhp = ldom_init(cpu_alloc, cpu_free);
+	if (lhp == NULL) {
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	status = ldom_fmri_status(lhp, in);
+	rc = (status == P_FAULTED ||
+		(status == P_OFFLINE && ldom_major_version(lhp) == 1));
+	ldom_fini(lhp);
+
+	/* return the unusable status */
+	if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) != 0)
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	if (nvlist_add_uint32(*out, TOPO_METH_UNUSABLE_RET, rc) != 0) {
+		nvlist_free(*out);
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
 	}
 
-	/*
-	 * N1 MD contains cpu nodes while N2 MD contains component nodes.
-	 */
-	if (md_find_name(mdp, MD_STR_COMPONENT) != MDE_INVAL_STR_COOKIE) {
-		rc = cpu_n2_mdesc_init(mod, mdp, chip);
-	} else if (md_find_name(mdp, MD_STR_CPU) != MDE_INVAL_STR_COOKIE) {
-		rc =  cpu_n1_mdesc_init(mod, mdp, chip);
-	} else {
-		topo_mod_dprintf(mod, "Unsupported PRI/MD\n");
-		rc = -1;
-	}
+	return (0);
+}
 
-	cpu_free(bufp, (size_t)bufsiz);
-	(void) md_fini(mdp);
-	ldom_fini(lhp);
-
-	return (rc);
-}
 
 static nvlist_t *
 cpu_fmri_create(topo_mod_t *mod, uint32_t cpuid, char *serial, uint8_t cpumask)
@@ -372,7 +332,7 @@
 
 /*ARGSUSED*/
 static int
-cpu_create(topo_mod_t *mod, tnode_t *rnode, const char *name, chip_t *chip)
+cpu_create(topo_mod_t *mod, tnode_t *rnode, const char *name, md_info_t *chip)
 {
 	int i;
 	int min = -1;
@@ -387,11 +347,11 @@
 	/*
 	 * find the min/max id of cpus per this cmp and create a cpu range
 	 */
-	for (i = 0; i < chip->chip_ncpus; i++) {
-		if ((min < 0) || (chip->chip_cpus[i].cpumap_pid < min))
-			min = chip->chip_cpus[i].cpumap_pid;
-		if ((max < 0) || (chip->chip_cpus[i].cpumap_pid > max))
-			max = chip->chip_cpus[i].cpumap_pid;
+	for (i = 0; i < chip->ncpus; i++) {
+		if ((min < 0) || (chip->cpus[i].cpumap_pid < min))
+			min = chip->cpus[i].cpumap_pid;
+		if ((max < 0) || (chip->cpus[i].cpumap_pid > max))
+			max = chip->cpus[i].cpumap_pid;
 	}
 	if (min < 0 || max < 0)
 		return (-1);
@@ -405,13 +365,13 @@
 	/*
 	 * Create the cpu nodes
 	 */
-	for (i = 0; i < chip->chip_ncpus; i++) {
+	for (i = 0; i < chip->ncpus; i++) {
 
 		(void) snprintf(sbuf, sizeof (sbuf), "%llx",
-			chip->chip_cpus[i].cpumap_serialno);
+			chip->cpus[i].cpumap_serialno);
 
 		/* physical cpuid */
-		pid = chip->chip_cpus[i].cpumap_pid;
+		pid = chip->cpus[i].cpumap_pid;
 		cnode = cpu_tnode_create(mod, rnode, name,
 					(topo_instance_t)pid, sbuf, NULL);
 		if (cnode == NULL) {
@@ -436,14 +396,22 @@
     topo_instance_t min, topo_instance_t max, void *arg, void *notused)
 {
 	topo_mod_dprintf(mod, "%s enumerating %s\n", PLATFORM_CPU_NAME, name);
+
+	if (topo_method_register(mod, rnode, cpu_methods) < 0) {
+		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
+		topo_strerror(topo_mod_errno(mod)));
+		return (-1);
+	}
+
 	if (strcmp(name, CPU_NODE_NAME) == 0)
-		return (cpu_create(mod, rnode, name, (chip_t *)arg));
+		return (cpu_create(mod, rnode, name, (md_info_t *)arg));
 
 	return (0);
 }
 
 /*ARGSUSED*/
 static void
-cpu_release(topo_mod_t *mp, tnode_t *node)
+cpu_release(topo_mod_t *mod, tnode_t *node)
 {
+	topo_method_unregister_all(mod, node);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu_mdesc.c	Mon Feb 19 20:47:33 2007 -0800
@@ -0,0 +1,356 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <string.h>
+#include <umem.h>
+#include <sys/mdesc.h>
+#include <sys/fm/ldom.h>
+
+#include <cpu_mdesc.h>
+
+static void *
+cpu_alloc(size_t size)
+{
+	return (umem_alloc(size, UMEM_DEFAULT));
+}
+
+static void
+cpu_free(void *data, size_t size)
+{
+	umem_free(data, size);
+}
+
+md_cpumap_t *
+cpu_find_cpumap(md_info_t *chip, uint32_t cpuid) {
+	int i;
+	md_cpumap_t *mcmp;
+
+	for (i = 0, mcmp = chip->cpus; i < chip->ncpus; i++, mcmp++) {
+		if (cpuid == mcmp->cpumap_pid) {
+			return (mcmp);
+		}
+	}
+	return (NULL);
+}
+
+int
+cpu_get_serialid_mdesc(md_info_t *chip, uint32_t cpuid, uint64_t *serialidp)
+{
+	md_cpumap_t *mcmp;
+	if ((mcmp = cpu_find_cpumap(chip, cpuid)) != NULL) {
+		*serialidp = mcmp->cpumap_serialno;
+		return (0);
+	}
+	return (-1);
+}
+
+static int
+cpu_n1_mdesc_init(topo_mod_t *mod, md_t *mdp, md_info_t *chip)
+{
+	mde_cookie_t *listp;
+	md_cpumap_t *mcmp;
+	int i, num_nodes, idx;
+	uint64_t x;
+
+	num_nodes = md_node_count(mdp);
+	listp = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * num_nodes);
+
+	chip->ncpus = md_scan_dag(mdp,
+				MDE_INVAL_ELEM_COOKIE,
+				md_find_name(mdp, "cpu"),
+				md_find_name(mdp, "fwd"),
+				listp);
+	topo_mod_dprintf(mod, "Found %d cpus\n", chip->ncpus);
+
+	chip->cpus = topo_mod_zalloc(mod, chip->ncpus * sizeof (md_cpumap_t));
+	chip->nprocs = chip->ncpus;
+	chip->procs = topo_mod_zalloc(mod, chip->nprocs * sizeof (md_proc_t));
+
+	for (idx = 0, mcmp = chip->cpus; idx < chip->ncpus; idx++, mcmp++) {
+		if (md_get_prop_val(mdp, listp[idx], MD_STR_ID, &x) < 0)
+			x = (uint64_t)-1; /* invalid value */
+		mcmp->cpumap_id = x;
+
+		if (md_get_prop_val(mdp, listp[idx], MD_STR_PID, &x) < 0)
+			x = mcmp->cpumap_id;
+		mcmp->cpumap_pid = x;
+
+		if (md_get_prop_val(mdp, listp[idx], MD_STR_CPU_SERIAL,
+		    &mcmp->cpumap_serialno) < 0)
+			mcmp->cpumap_serialno = 0;
+
+		/*
+		 * This PRI/MD has no indentity info. of the FRU.
+		 * Find if there is already an existing processor entry
+		 */
+		for (i = 0; i < chip->nprocs &&
+		    chip->procs[i].serialno != 0; i++) {
+			if (mcmp->cpumap_serialno == chip->procs[i].serialno) {
+				break;
+			}
+		}
+		if (i < chip->nprocs) {
+			mcmp->cpumap_chipidx = i;
+			if (chip->procs[i].serialno == 0) {
+				chip->procs[i].serialno = mcmp->cpumap_serialno;
+				topo_mod_dprintf(mod,
+						"chip[%d] serial is %llx\n",
+						i, chip->procs[i].serialno);
+			}
+		}
+
+	}
+
+	topo_mod_free(mod, listp, sizeof (mde_cookie_t) * num_nodes);
+
+	return (0);
+}
+
+static int
+cpu_n2_mdesc_init(topo_mod_t *mod, md_t *mdp, md_info_t *chip)
+{
+	mde_cookie_t *list1p, *list2p;
+	md_cpumap_t *mcmp;
+	md_proc_t *procp;
+	md_fru_t *frup;
+	int i, j, cnt;
+	int nnode, ncomp, nproc, ncpu;
+	char *str = NULL;
+	uint64_t x, sn;
+
+	nnode = md_node_count(mdp);
+	list1p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode);
+
+	/* Count the number of processors and strands */
+	ncomp = md_scan_dag(mdp,
+			MDE_INVAL_ELEM_COOKIE,
+			md_find_name(mdp, MD_STR_COMPONENT),
+			md_find_name(mdp, "fwd"),
+			list1p);
+	if (ncomp <= 0) {
+		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
+		return (-1);
+	}
+	for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) {
+		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 &&
+		    str != NULL && strcmp(str, MD_STR_PROCESSOR) == 0) {
+			nproc++;
+		}
+		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 &&
+		    str && strcmp(str, MD_STR_STRAND) == 0) {
+			ncpu++;
+		}
+	}
+	topo_mod_dprintf(mod, "Found %d procs and %d strands\n", nproc, ncpu);
+	if (nproc == 0 || ncpu == 0) {
+		topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
+		return (-1);
+	}
+
+	/* Alloc processors and strand entries */
+	list2p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * 2 * ncpu);
+	chip->nprocs = nproc;
+	chip->procs = topo_mod_zalloc(mod, nproc * sizeof (md_proc_t));
+	chip->ncpus = ncpu;
+	chip->cpus = topo_mod_zalloc(mod, ncpu * sizeof (md_cpumap_t));
+
+	/* Visit each processor node */
+	procp = chip->procs;
+	mcmp = chip->cpus;
+	for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) {
+		if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) < 0 ||
+		    str == NULL || strcmp(str, MD_STR_PROCESSOR))
+			continue;
+		if (md_get_prop_val(mdp, list1p[i], MD_STR_SERIAL, &sn) < 0) {
+			topo_mod_dprintf(mod,
+				"Failed to get the serial number of proc[%d]\n",
+				nproc);
+			continue;
+		}
+		procp->serialno = sn;
+		topo_mod_dprintf(mod, "proc %d : sn=%llx\n", nproc, sn);
+		nproc++;
+
+		/* Get all the strands below this proc */
+		cnt = md_scan_dag(mdp,
+				list1p[i],
+				md_find_name(mdp, MD_STR_COMPONENT),
+				md_find_name(mdp, "fwd"),
+				list2p);
+		topo_mod_dprintf(mod, "proc[%llx]: Found %d fwd components\n",
+				sn, cnt);
+		if (cnt <= 0) {
+			procp++;
+			continue;
+		}
+		for (j = 0; j < cnt; j++) {
+			/* Consider only the strand nodes */
+			if (md_get_prop_str(mdp, list2p[j], MD_STR_TYPE, &str)
+			    < 0 || str == NULL || strcmp(str, MD_STR_STRAND))
+				continue;
+
+			ncpu++;
+			if (md_get_prop_val(mdp, list2p[j], MD_STR_ID, &x) < 0)
+				x = (uint64_t)-1; /* invalid value */
+			mcmp->cpumap_id = x;
+
+			if (md_get_prop_val(mdp, list2p[j], MD_STR_PID, &x) < 0)
+				x = mcmp->cpumap_id;
+			mcmp->cpumap_pid = x;
+
+			mcmp->cpumap_serialno = sn;
+			mcmp->cpumap_chipidx = nproc - 1;
+			mcmp++;
+		}
+
+		/*
+		 * To get the fru of this proc, follow the back arc up to
+		 * find the first node whose fru field is set
+		 */
+		cnt = md_scan_dag(mdp,
+				list1p[i],
+				md_find_name(mdp, MD_STR_COMPONENT),
+				md_find_name(mdp, "back"),
+				list2p);
+		topo_mod_dprintf(mod, "proc[%d]: Found %d back components\n",
+				nproc-1, cnt);
+		if (cnt <= 0) {
+			procp++;
+			continue;
+		}
+		for (j = 0; j < cnt; j++) {
+			/* test the fru field which must be positive number */
+			if ((md_get_prop_val(mdp, list2p[j], MD_STR_FRU, &x)
+				== 0) && x > 0)
+				break;
+		}
+		if (j < cnt) {
+			/* Found the FRU node, get the fru identity */
+			topo_mod_dprintf(mod, "proc[%d] sn=%llx has a fru %d\n",
+				nproc-1, procp->serialno, j);
+			frup = topo_mod_zalloc(mod, sizeof (md_fru_t));
+			procp->fru = frup;
+			if (!md_get_prop_str(mdp, list2p[j], MD_STR_NAC, &str))
+				frup->nac = topo_mod_strdup(mod, str);
+			else
+				frup->nac = topo_mod_strdup(mod, MD_FRU_DEF);
+			if (!md_get_prop_str(mdp, list2p[j], MD_STR_PART, &str))
+				frup->part = topo_mod_strdup(mod, str);
+			if (!md_get_prop_str(mdp, list2p[j], MD_STR_SERIAL,
+			    &str))
+				frup->serial = topo_mod_strdup(mod, str);
+			if (!md_get_prop_str(mdp, list2p[j], MD_STR_DASH, &str))
+				frup->dash = topo_mod_strdup(mod, str);
+		} else {
+			topo_mod_dprintf(mod, "proc[%d] sn=%llx has no fru\n",
+				i, procp->serialno);
+		}
+		procp++;
+	} /* for i */
+
+	topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode);
+	topo_mod_free(mod, list2p, sizeof (mde_cookie_t) * 2*chip->ncpus);
+
+	return (0);
+}
+
+/*
+ * Extract from the PRI the processor, strand and their fru identity
+ */
+int
+cpu_mdesc_init(topo_mod_t *mod, md_info_t *chip)
+{
+	int rc = -1;
+	md_t *mdp;
+	ssize_t bufsiz = 0;
+	uint64_t *bufp;
+	ldom_hdl_t *lhp;
+
+	/* get the PRI/MD */
+	if ((lhp = ldom_init(cpu_alloc, cpu_free)) == NULL) {
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+	if ((bufsiz = ldom_get_core_md(lhp, &bufp)) <= 0) {
+		topo_mod_dprintf(mod, "failed to get the PRI/MD\n");
+		ldom_fini(lhp);
+		return (-1);
+	}
+
+	if ((mdp = md_init_intern(bufp, cpu_alloc, cpu_free)) == NULL ||
+	    md_node_count(mdp) <= 0) {
+		cpu_free(bufp, (size_t)bufsiz);
+		ldom_fini(lhp);
+		return (-1);
+	}
+
+	/*
+	 * N1 MD contains cpu nodes while N2 MD contains component nodes.
+	 */
+	if (md_find_name(mdp, MD_STR_COMPONENT) != MDE_INVAL_STR_COOKIE) {
+		rc = cpu_n2_mdesc_init(mod, mdp, chip);
+	} else if (md_find_name(mdp, MD_STR_CPU) != MDE_INVAL_STR_COOKIE) {
+		rc =  cpu_n1_mdesc_init(mod, mdp, chip);
+	} else {
+		topo_mod_dprintf(mod, "Unsupported PRI/MD\n");
+		rc = -1;
+	}
+
+	cpu_free(bufp, (size_t)bufsiz);
+	(void) md_fini(mdp);
+	ldom_fini(lhp);
+
+	return (rc);
+}
+
+void
+cpu_mdesc_fini(topo_mod_t *mod, md_info_t *chip)
+{
+	int i;
+	md_proc_t *procp;
+	md_fru_t *frup;
+
+	if (chip->cpus != NULL)
+		topo_mod_free(mod, chip->cpus,
+			chip->ncpus * sizeof (md_cpumap_t));
+
+	if (chip->procs != NULL) {
+		procp = chip->procs;
+		for (i = 0; i < chip->nprocs; i++) {
+			if ((frup = procp->fru) != NULL) {
+				topo_mod_strfree(mod, frup->nac);
+				topo_mod_strfree(mod, frup->serial);
+				topo_mod_strfree(mod, frup->part);
+				topo_mod_strfree(mod, frup->dash);
+				topo_mod_free(mod, frup, sizeof (md_fru_t));
+			}
+			procp++;
+		}
+		topo_mod_free(mod, chip->procs,
+			chip->nprocs * sizeof (md_proc_t));
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/sun4v/platform-cpu/cpu_mdesc.h	Mon Feb 19 20:47:33 2007 -0800
@@ -0,0 +1,96 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_CPU_MDESC_H
+#define	_CPU_MDESC_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <fm/topo_mod.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Node/Field names in the PRI/MD
+ */
+#define	MD_STR_ID		"id"
+#define	MD_STR_PID		"pid"
+#define	MD_STR_CPU_SERIAL	"serial#"
+#define	MD_STR_CPU		"cpu"
+#define	MD_STR_COMPONENT	"component"
+#define	MD_STR_TYPE		"type"
+#define	MD_STR_PROCESSOR	"processor"
+#define	MD_STR_STRAND		"strand"
+#define	MD_STR_FRU		"fru"
+#define	MD_STR_NAC		"nac"
+#define	MD_STR_SERIAL		"serial_number"
+#define	MD_STR_PART		"part_number"
+#define	MD_STR_DASH		"dash_number"
+
+#define	MD_FRU_DEF		"MB"
+#define	MD_STR_BLANK		""
+
+typedef struct md_cpumap {
+	uint32_t cpumap_id;		/* virtual cpuid */
+	uint32_t cpumap_pid;		/* physical cpuid */
+	uint64_t cpumap_serialno;	/* cpu serial number */
+	int cpumap_chipidx;		/* chip idx */
+} md_cpumap_t;
+
+typedef struct md_fru {
+	char *nac;			/* FRU or nac */
+	char *serial;			/* FRU serial */
+	char *part;			/* FRU part number */
+	char *dash;			/* FRU dash */
+} md_fru_t;
+
+typedef struct md_proc {
+	uint64_t serialno;		/* processor serial number */
+	md_fru_t *fru;			/* FRU info */
+} md_proc_t;
+
+typedef struct md_info {
+	md_proc_t *procs;		/* list of processors */
+	uint32_t nprocs;		/* size */
+	md_cpumap_t *cpus;		/* List of cpu maps */
+	uint32_t ncpus;			/* size */
+} md_info_t;
+
+
+extern int cpu_mdesc_init(topo_mod_t *mod, md_info_t *chip);
+extern void cpu_mdesc_fini(topo_mod_t *mod, md_info_t *chip);
+
+extern int cpu_get_serialid_mdesc(md_info_t *chip, uint32_t cpuid,
+					uint64_t *serialno);
+extern md_cpumap_t *cpu_find_cpumap(md_info_t *chip, uint32_t cpuid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CPU_MDESC_H */