17532SSean.Ye@Sun.COM /*
27532SSean.Ye@Sun.COM  * CDDL HEADER START
37532SSean.Ye@Sun.COM  *
47532SSean.Ye@Sun.COM  * The contents of this file are subject to the terms of the
57532SSean.Ye@Sun.COM  * Common Development and Distribution License (the "License").
67532SSean.Ye@Sun.COM  * You may not use this file except in compliance with the License.
77532SSean.Ye@Sun.COM  *
87532SSean.Ye@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97532SSean.Ye@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107532SSean.Ye@Sun.COM  * See the License for the specific language governing permissions
117532SSean.Ye@Sun.COM  * and limitations under the License.
127532SSean.Ye@Sun.COM  *
137532SSean.Ye@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147532SSean.Ye@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157532SSean.Ye@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167532SSean.Ye@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177532SSean.Ye@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187532SSean.Ye@Sun.COM  *
197532SSean.Ye@Sun.COM  * CDDL HEADER END
207532SSean.Ye@Sun.COM  */
217532SSean.Ye@Sun.COM /*
22*10942STom.Pothier@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237532SSean.Ye@Sun.COM  * Use is subject to license terms.
247532SSean.Ye@Sun.COM  */
257532SSean.Ye@Sun.COM 
267532SSean.Ye@Sun.COM #include <sys/stat.h>
277532SSean.Ye@Sun.COM #include <sys/types.h>
287532SSean.Ye@Sun.COM #include <sys/time.h>
297532SSean.Ye@Sun.COM 
307532SSean.Ye@Sun.COM #include <sys/fm/protocol.h>
31*10942STom.Pothier@Sun.COM #include <sys/fm/smb/fmsmb.h>
327532SSean.Ye@Sun.COM #include <sys/devfm.h>
337532SSean.Ye@Sun.COM 
347532SSean.Ye@Sun.COM #include <sys/cpu_module.h>
357532SSean.Ye@Sun.COM 
367532SSean.Ye@Sun.COM #define	ANY_ID		(uint_t)-1
377532SSean.Ye@Sun.COM 
387532SSean.Ye@Sun.COM /*
397532SSean.Ye@Sun.COM  * INIT_HDLS is the initial size of cmi_hdl_t array.  We fill the array
407532SSean.Ye@Sun.COM  * during cmi_hdl_walk, if the array overflows, we will reallocate
417532SSean.Ye@Sun.COM  * a new array twice the size of the old one.
427532SSean.Ye@Sun.COM  */
437532SSean.Ye@Sun.COM #define	INIT_HDLS	16
447532SSean.Ye@Sun.COM 
457532SSean.Ye@Sun.COM typedef struct fm_cmi_walk_t
467532SSean.Ye@Sun.COM {
477532SSean.Ye@Sun.COM 	uint_t	chipid;		/* chipid to match during walk */
487532SSean.Ye@Sun.COM 	uint_t	coreid;		/* coreid to match */
497532SSean.Ye@Sun.COM 	uint_t	strandid;	/* strandid to match */
507532SSean.Ye@Sun.COM 	int	(*cbfunc)(cmi_hdl_t, void *, void *);  	/* callback function */
517532SSean.Ye@Sun.COM 	cmi_hdl_t *hdls;	/* allocated array to save the handles */
527532SSean.Ye@Sun.COM 	int	nhdl_max;	/* allocated array size */
537532SSean.Ye@Sun.COM 	int	nhdl;		/* handles saved */
547532SSean.Ye@Sun.COM } fm_cmi_walk_t;
557532SSean.Ye@Sun.COM 
56*10942STom.Pothier@Sun.COM extern int x86gentopo_legacy;
57*10942STom.Pothier@Sun.COM 
587532SSean.Ye@Sun.COM int
597532SSean.Ye@Sun.COM fm_get_paddr(nvlist_t *nvl, uint64_t *paddr)
607532SSean.Ye@Sun.COM {
617532SSean.Ye@Sun.COM 	uint8_t version;
627532SSean.Ye@Sun.COM 	uint64_t pa;
637532SSean.Ye@Sun.COM 	char *scheme;
647532SSean.Ye@Sun.COM 	int err;
657532SSean.Ye@Sun.COM 
667532SSean.Ye@Sun.COM 	/* Verify FMRI scheme name and version number */
677532SSean.Ye@Sun.COM 	if ((nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme) != 0) ||
687532SSean.Ye@Sun.COM 	    (strcmp(scheme, FM_FMRI_SCHEME_HC) != 0) ||
697532SSean.Ye@Sun.COM 	    (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0) ||
707532SSean.Ye@Sun.COM 	    version > FM_HC_SCHEME_VERSION) {
717532SSean.Ye@Sun.COM 		return (EINVAL);
727532SSean.Ye@Sun.COM 	}
737532SSean.Ye@Sun.COM 
747532SSean.Ye@Sun.COM 	if ((err = cmi_mc_unumtopa(NULL, nvl, &pa)) != CMI_SUCCESS &&
757532SSean.Ye@Sun.COM 	    err != CMIERR_MC_PARTIALUNUMTOPA)
767532SSean.Ye@Sun.COM 		return (EINVAL);
777532SSean.Ye@Sun.COM 
787532SSean.Ye@Sun.COM 	*paddr = pa;
797532SSean.Ye@Sun.COM 	return (0);
807532SSean.Ye@Sun.COM }
817532SSean.Ye@Sun.COM 
827532SSean.Ye@Sun.COM /*
837532SSean.Ye@Sun.COM  * Routines for cmi handles walk.
847532SSean.Ye@Sun.COM  */
857532SSean.Ye@Sun.COM 
867532SSean.Ye@Sun.COM static void
877532SSean.Ye@Sun.COM walk_init(fm_cmi_walk_t *wp, uint_t chipid, uint_t coreid, uint_t strandid,
887532SSean.Ye@Sun.COM     int (*cbfunc)(cmi_hdl_t, void *, void *))
897532SSean.Ye@Sun.COM {
907532SSean.Ye@Sun.COM 	wp->chipid = chipid;
917532SSean.Ye@Sun.COM 	wp->coreid = coreid;
927532SSean.Ye@Sun.COM 	wp->strandid = strandid;
937532SSean.Ye@Sun.COM 	/*
947532SSean.Ye@Sun.COM 	 * If callback is not set, we allocate an array to save the
957532SSean.Ye@Sun.COM 	 * cmi handles.
967532SSean.Ye@Sun.COM 	 */
977532SSean.Ye@Sun.COM 	if ((wp->cbfunc = cbfunc) == NULL) {
987532SSean.Ye@Sun.COM 		wp->hdls = kmem_alloc(sizeof (cmi_hdl_t) * INIT_HDLS, KM_SLEEP);
997532SSean.Ye@Sun.COM 		wp->nhdl_max = INIT_HDLS;
1007532SSean.Ye@Sun.COM 		wp->nhdl = 0;
1017532SSean.Ye@Sun.COM 	}
1027532SSean.Ye@Sun.COM }
1037532SSean.Ye@Sun.COM 
1047532SSean.Ye@Sun.COM static void
1057532SSean.Ye@Sun.COM walk_fini(fm_cmi_walk_t *wp)
1067532SSean.Ye@Sun.COM {
1077532SSean.Ye@Sun.COM 	if (wp->cbfunc == NULL)
1087532SSean.Ye@Sun.COM 		kmem_free(wp->hdls, sizeof (cmi_hdl_t) * wp->nhdl_max);
1097532SSean.Ye@Sun.COM }
1107532SSean.Ye@Sun.COM 
1117532SSean.Ye@Sun.COM static int
1127532SSean.Ye@Sun.COM select_cmi_hdl(cmi_hdl_t hdl, void *arg1, void *arg2, void *arg3)
1137532SSean.Ye@Sun.COM {
1147532SSean.Ye@Sun.COM 	fm_cmi_walk_t *wp = (fm_cmi_walk_t *)arg1;
1157532SSean.Ye@Sun.COM 
1167532SSean.Ye@Sun.COM 	if (wp->chipid != ANY_ID && wp->chipid != cmi_hdl_chipid(hdl))
1177532SSean.Ye@Sun.COM 		return (CMI_HDL_WALK_NEXT);
1187532SSean.Ye@Sun.COM 	if (wp->coreid != ANY_ID && wp->coreid != cmi_hdl_coreid(hdl))
1197532SSean.Ye@Sun.COM 		return (CMI_HDL_WALK_NEXT);
1207532SSean.Ye@Sun.COM 	if (wp->strandid != ANY_ID && wp->strandid != cmi_hdl_strandid(hdl))
1217532SSean.Ye@Sun.COM 		return (CMI_HDL_WALK_NEXT);
1227532SSean.Ye@Sun.COM 
1237532SSean.Ye@Sun.COM 	/*
1247532SSean.Ye@Sun.COM 	 * Call the callback function if any exists, otherwise we hold a
1257532SSean.Ye@Sun.COM 	 * reference of the handle and push it to preallocated array.
1267532SSean.Ye@Sun.COM 	 * If the allocated array is going to overflow, reallocate a
1277532SSean.Ye@Sun.COM 	 * bigger one to replace it.
1287532SSean.Ye@Sun.COM 	 */
1297532SSean.Ye@Sun.COM 	if (wp->cbfunc != NULL)
1307532SSean.Ye@Sun.COM 		return (wp->cbfunc(hdl, arg2, arg3));
1317532SSean.Ye@Sun.COM 
1327532SSean.Ye@Sun.COM 	if (wp->nhdl == wp->nhdl_max) {
1337532SSean.Ye@Sun.COM 		size_t sz = sizeof (cmi_hdl_t) * wp->nhdl_max;
1347532SSean.Ye@Sun.COM 		cmi_hdl_t *newarray = kmem_alloc(sz << 1, KM_SLEEP);
1357532SSean.Ye@Sun.COM 
1367532SSean.Ye@Sun.COM 		bcopy(wp->hdls, newarray, sz);
1377532SSean.Ye@Sun.COM 		kmem_free(wp->hdls, sz);
1387532SSean.Ye@Sun.COM 		wp->hdls = newarray;
1397532SSean.Ye@Sun.COM 		wp->nhdl_max <<= 1;
1407532SSean.Ye@Sun.COM 	}
1417532SSean.Ye@Sun.COM 
1427532SSean.Ye@Sun.COM 	cmi_hdl_hold(hdl);
1437532SSean.Ye@Sun.COM 	wp->hdls[wp->nhdl++] = hdl;
1447532SSean.Ye@Sun.COM 
1457532SSean.Ye@Sun.COM 	return (CMI_HDL_WALK_NEXT);
1467532SSean.Ye@Sun.COM }
1477532SSean.Ye@Sun.COM 
1487532SSean.Ye@Sun.COM static void
1497532SSean.Ye@Sun.COM populate_cpu(nvlist_t **nvlp, cmi_hdl_t hdl)
1507532SSean.Ye@Sun.COM {
151*10942STom.Pothier@Sun.COM 	uint_t	fm_chipid;
152*10942STom.Pothier@Sun.COM 	uint16_t smbios_id;
153*10942STom.Pothier@Sun.COM 
1547532SSean.Ye@Sun.COM 	(void) nvlist_alloc(nvlp, NV_UNIQUE_NAME, KM_SLEEP);
155*10942STom.Pothier@Sun.COM 
156*10942STom.Pothier@Sun.COM 	/*
157*10942STom.Pothier@Sun.COM 	 * If SMBIOS satisfies FMA Topology needs, gather
158*10942STom.Pothier@Sun.COM 	 * more information on the chip's physical roots
159*10942STom.Pothier@Sun.COM 	 * like /chassis=x/motherboard=y/cpuboard=z and
160*10942STom.Pothier@Sun.COM 	 * set the chip_id to match the SMBIOS' Type 4
161*10942STom.Pothier@Sun.COM 	 * ordering & this has to match the ereport's chip
162*10942STom.Pothier@Sun.COM 	 * resource instance derived off of SMBIOS.
163*10942STom.Pothier@Sun.COM 	 * Multi-Chip-Module support should set the chipid
164*10942STom.Pothier@Sun.COM 	 * in terms of the processor package rather than
165*10942STom.Pothier@Sun.COM 	 * the die/node in the processor package, for FM.
166*10942STom.Pothier@Sun.COM 	 */
167*10942STom.Pothier@Sun.COM 
168*10942STom.Pothier@Sun.COM 	if (!x86gentopo_legacy) {
169*10942STom.Pothier@Sun.COM 		smbios_id = cmi_hdl_smbiosid(hdl);
170*10942STom.Pothier@Sun.COM 		fm_chipid = cmi_hdl_smb_chipid(hdl);
171*10942STom.Pothier@Sun.COM 		(void) nvlist_add_nvlist(*nvlp, FM_PHYSCPU_INFO_CHIP_ROOTS,
172*10942STom.Pothier@Sun.COM 		    cmi_hdl_smb_bboard(hdl));
173*10942STom.Pothier@Sun.COM 		(void) nvlist_add_uint16(*nvlp, FM_PHYSCPU_INFO_SMBIOS_ID,
174*10942STom.Pothier@Sun.COM 		    (uint16_t)smbios_id);
175*10942STom.Pothier@Sun.COM 	} else
176*10942STom.Pothier@Sun.COM 		fm_chipid = cmi_hdl_chipid(hdl);
177*10942STom.Pothier@Sun.COM 
1787532SSean.Ye@Sun.COM 	fm_payload_set(*nvlp,
1797532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING,
1807532SSean.Ye@Sun.COM 	    cmi_hdl_vendorstr(hdl),
1817532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32,
1827532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_family(hdl),
1837532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32,
1847532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_model(hdl),
1857532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_STEPPING, DATA_TYPE_INT32,
1867532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_stepping(hdl),
1877532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32,
188*10942STom.Pothier@Sun.COM 	    (int32_t)fm_chipid,
1897532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CORE_ID, DATA_TYPE_INT32,
1907532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_coreid(hdl),
1917532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_STRAND_ID, DATA_TYPE_INT32,
1927532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_strandid(hdl),
193*10942STom.Pothier@Sun.COM 	    FM_PHYSCPU_INFO_STRAND_APICID, DATA_TYPE_INT32,
194*10942STom.Pothier@Sun.COM 	    (int32_t)cmi_hdl_strand_apicid(hdl),
1957532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CHIP_REV, DATA_TYPE_STRING,
1967532SSean.Ye@Sun.COM 	    cmi_hdl_chiprevstr(hdl),
1977532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_SOCKET_TYPE, DATA_TYPE_UINT32,
1987532SSean.Ye@Sun.COM 	    (uint32_t)cmi_hdl_getsockettype(hdl),
1997532SSean.Ye@Sun.COM 	    FM_PHYSCPU_INFO_CPU_ID, DATA_TYPE_INT32,
2007532SSean.Ye@Sun.COM 	    (int32_t)cmi_hdl_logical_id(hdl),
2017532SSean.Ye@Sun.COM 	    NULL);
2027532SSean.Ye@Sun.COM }
2037532SSean.Ye@Sun.COM 
2047532SSean.Ye@Sun.COM /*ARGSUSED*/
2057532SSean.Ye@Sun.COM int
2067532SSean.Ye@Sun.COM fm_ioctl_physcpu_info(int cmd, nvlist_t *invl, nvlist_t **onvlp)
2077532SSean.Ye@Sun.COM {
2087532SSean.Ye@Sun.COM 	nvlist_t **cpus, *nvl;
2097532SSean.Ye@Sun.COM 	int i, err;
2107532SSean.Ye@Sun.COM 	fm_cmi_walk_t wk;
2117532SSean.Ye@Sun.COM 
2127532SSean.Ye@Sun.COM 	/*
2137532SSean.Ye@Sun.COM 	 * Do a walk to save all the cmi handles in the array.
2147532SSean.Ye@Sun.COM 	 */
2157532SSean.Ye@Sun.COM 	walk_init(&wk, ANY_ID, ANY_ID, ANY_ID, NULL);
2167532SSean.Ye@Sun.COM 	cmi_hdl_walk(select_cmi_hdl, &wk, NULL, NULL);
2177532SSean.Ye@Sun.COM 
2187532SSean.Ye@Sun.COM 	if (wk.nhdl == 0) {
2197532SSean.Ye@Sun.COM 		walk_fini(&wk);
2207532SSean.Ye@Sun.COM 		return (ENOENT);
2217532SSean.Ye@Sun.COM 	}
2227532SSean.Ye@Sun.COM 
2237532SSean.Ye@Sun.COM 	cpus = kmem_alloc(sizeof (nvlist_t *) * wk.nhdl, KM_SLEEP);
2247532SSean.Ye@Sun.COM 	for (i = 0; i < wk.nhdl; i++) {
2257532SSean.Ye@Sun.COM 		populate_cpu(cpus + i, wk.hdls[i]);
2267532SSean.Ye@Sun.COM 		cmi_hdl_rele(wk.hdls[i]);
2277532SSean.Ye@Sun.COM 	}
2287532SSean.Ye@Sun.COM 
2297532SSean.Ye@Sun.COM 	walk_fini(&wk);
2307532SSean.Ye@Sun.COM 
2317532SSean.Ye@Sun.COM 	(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
2327532SSean.Ye@Sun.COM 	err = nvlist_add_nvlist_array(nvl, FM_PHYSCPU_INFO_CPUS,
2337532SSean.Ye@Sun.COM 	    cpus, wk.nhdl);
2347532SSean.Ye@Sun.COM 
2357532SSean.Ye@Sun.COM 	for (i = 0; i < wk.nhdl; i++)
2367532SSean.Ye@Sun.COM 		nvlist_free(cpus[i]);
2377532SSean.Ye@Sun.COM 	kmem_free(cpus, sizeof (nvlist_t *) * wk.nhdl);
2387532SSean.Ye@Sun.COM 
2397532SSean.Ye@Sun.COM 	if (err != 0) {
2407532SSean.Ye@Sun.COM 		nvlist_free(nvl);
2417532SSean.Ye@Sun.COM 		return (err);
2427532SSean.Ye@Sun.COM 	}
2437532SSean.Ye@Sun.COM 
2447532SSean.Ye@Sun.COM 	*onvlp = nvl;
2457532SSean.Ye@Sun.COM 	return (0);
2467532SSean.Ye@Sun.COM }
2477532SSean.Ye@Sun.COM 
2487532SSean.Ye@Sun.COM int
2497532SSean.Ye@Sun.COM fm_ioctl_cpu_retire(int cmd, nvlist_t *invl, nvlist_t **onvlp)
2507532SSean.Ye@Sun.COM {
2517532SSean.Ye@Sun.COM 	int32_t chipid, coreid, strandid;
2527532SSean.Ye@Sun.COM 	int rc, new_status, old_status;
2537532SSean.Ye@Sun.COM 	cmi_hdl_t hdl;
2547532SSean.Ye@Sun.COM 	nvlist_t *nvl;
2557532SSean.Ye@Sun.COM 
2567532SSean.Ye@Sun.COM 	switch (cmd) {
2577532SSean.Ye@Sun.COM 	case FM_IOC_CPU_RETIRE:
2587532SSean.Ye@Sun.COM 		new_status = P_FAULTED;
2597532SSean.Ye@Sun.COM 		break;
2607532SSean.Ye@Sun.COM 	case FM_IOC_CPU_STATUS:
2617532SSean.Ye@Sun.COM 		new_status = P_STATUS;
2627532SSean.Ye@Sun.COM 		break;
2637532SSean.Ye@Sun.COM 	case FM_IOC_CPU_UNRETIRE:
2647532SSean.Ye@Sun.COM 		new_status = P_ONLINE;
2657532SSean.Ye@Sun.COM 		break;
2667532SSean.Ye@Sun.COM 	default:
2677532SSean.Ye@Sun.COM 		return (ENOTTY);
2687532SSean.Ye@Sun.COM 	}
2697532SSean.Ye@Sun.COM 
2707532SSean.Ye@Sun.COM 	if (nvlist_lookup_int32(invl, FM_CPU_RETIRE_CHIP_ID, &chipid) != 0 ||
2717532SSean.Ye@Sun.COM 	    nvlist_lookup_int32(invl, FM_CPU_RETIRE_CORE_ID, &coreid) != 0 ||
2727532SSean.Ye@Sun.COM 	    nvlist_lookup_int32(invl, FM_CPU_RETIRE_STRAND_ID, &strandid) != 0)
2737532SSean.Ye@Sun.COM 		return (EINVAL);
2747532SSean.Ye@Sun.COM 
2757532SSean.Ye@Sun.COM 	hdl = cmi_hdl_lookup(CMI_HDL_NEUTRAL, chipid, coreid, strandid);
2767532SSean.Ye@Sun.COM 	if (hdl == NULL)
2777532SSean.Ye@Sun.COM 		return (EINVAL);
2787532SSean.Ye@Sun.COM 
2797532SSean.Ye@Sun.COM 	rc = cmi_hdl_online(hdl, new_status, &old_status);
2807532SSean.Ye@Sun.COM 	cmi_hdl_rele(hdl);
2817532SSean.Ye@Sun.COM 
2827532SSean.Ye@Sun.COM 	if (rc == 0) {
2837532SSean.Ye@Sun.COM 		(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
2847532SSean.Ye@Sun.COM 		(void) nvlist_add_int32(nvl, FM_CPU_RETIRE_OLDSTATUS,
2857532SSean.Ye@Sun.COM 		    old_status);
2867532SSean.Ye@Sun.COM 		*onvlp = nvl;
2877532SSean.Ye@Sun.COM 	}
2887532SSean.Ye@Sun.COM 
2897532SSean.Ye@Sun.COM 	return (rc);
2907532SSean.Ye@Sun.COM }
291*10942STom.Pothier@Sun.COM 
292*10942STom.Pothier@Sun.COM /*
293*10942STom.Pothier@Sun.COM  * Retrun the value of x86gentopo_legacy variable as an nvpair.
294*10942STom.Pothier@Sun.COM  *
295*10942STom.Pothier@Sun.COM  * The caller is responsible for freeing the nvlist.
296*10942STom.Pothier@Sun.COM  */
297*10942STom.Pothier@Sun.COM /* ARGSUSED */
298*10942STom.Pothier@Sun.COM int
299*10942STom.Pothier@Sun.COM fm_ioctl_gentopo_legacy(int cmd, nvlist_t *invl, nvlist_t **onvlp)
300*10942STom.Pothier@Sun.COM {
301*10942STom.Pothier@Sun.COM 	nvlist_t *nvl;
302*10942STom.Pothier@Sun.COM 
303*10942STom.Pothier@Sun.COM 	if (cmd != FM_IOC_GENTOPO_LEGACY) {
304*10942STom.Pothier@Sun.COM 		return (ENOTTY);
305*10942STom.Pothier@Sun.COM 	}
306*10942STom.Pothier@Sun.COM 
307*10942STom.Pothier@Sun.COM 	/*
308*10942STom.Pothier@Sun.COM 	 * Inform the caller of the intentions of the ereport generators to
309*10942STom.Pothier@Sun.COM 	 * generate either a "generic" or "legacy" x86 topology.
310*10942STom.Pothier@Sun.COM 	 */
311*10942STom.Pothier@Sun.COM 
312*10942STom.Pothier@Sun.COM 	(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
313*10942STom.Pothier@Sun.COM 	(void) nvlist_add_int32(nvl, FM_GENTOPO_LEGACY, x86gentopo_legacy);
314*10942STom.Pothier@Sun.COM 	*onvlp = nvl;
315*10942STom.Pothier@Sun.COM 
316*10942STom.Pothier@Sun.COM 	return (0);
317*10942STom.Pothier@Sun.COM }
318