17aec1d6eScindi /*
27aec1d6eScindi  * CDDL HEADER START
37aec1d6eScindi  *
47aec1d6eScindi  * The contents of this file are subject to the terms of the
57aec1d6eScindi  * Common Development and Distribution License (the "License").
67aec1d6eScindi  * You may not use this file except in compliance with the License.
77aec1d6eScindi  *
87aec1d6eScindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97aec1d6eScindi  * or http://www.opensolaris.org/os/licensing.
107aec1d6eScindi  * See the License for the specific language governing permissions
117aec1d6eScindi  * and limitations under the License.
127aec1d6eScindi  *
137aec1d6eScindi  * When distributing Covered Code, include this CDDL HEADER in each
147aec1d6eScindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157aec1d6eScindi  * If applicable, add the following below this CDDL HEADER, with the
167aec1d6eScindi  * fields enclosed by brackets "[]" replaced with your own identifying
177aec1d6eScindi  * information: Portions Copyright [yyyy] [name of copyright owner]
187aec1d6eScindi  *
197aec1d6eScindi  * CDDL HEADER END
207aec1d6eScindi  */
217aec1d6eScindi 
227aec1d6eScindi /*
23c93c462eSCheng Sean Ye  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247aec1d6eScindi  * Use is subject to license terms.
25*f2dbfd32SRobert Mustacchi  * Copyright 2019, Joyent, Inc.
267aec1d6eScindi  */
277aec1d6eScindi 
287aec1d6eScindi #include <unistd.h>
29e4b86885SCheng Sean Ye #include <fcntl.h>
307aec1d6eScindi #include <stdio.h>
317aec1d6eScindi #include <stdlib.h>
328a40a695Sgavinm #include <stdarg.h>
337aec1d6eScindi #include <string.h>
347aec1d6eScindi #include <strings.h>
357aec1d6eScindi #include <limits.h>
367aec1d6eScindi #include <alloca.h>
377aec1d6eScindi #include <kstat.h>
387aec1d6eScindi #include <errno.h>
397aec1d6eScindi #include <libnvpair.h>
407aec1d6eScindi #include <sys/types.h>
417aec1d6eScindi #include <sys/bitmap.h>
427aec1d6eScindi #include <sys/processor.h>
437aec1d6eScindi #include <sys/param.h>
447aec1d6eScindi #include <sys/fm/protocol.h>
457aec1d6eScindi #include <sys/systeminfo.h>
467aec1d6eScindi #include <sys/mc.h>
478a40a695Sgavinm #include <sys/mc_amd.h>
4820c794b3Sgavinm #include <sys/mc_intel.h>
49e4b86885SCheng Sean Ye #include <sys/devfm.h>
50e4b86885SCheng Sean Ye #include <fm/fmd_agent.h>
517aec1d6eScindi #include <fm/topo_mod.h>
527aec1d6eScindi 
537aec1d6eScindi #include "chip.h"
547aec1d6eScindi 
55bac58072Sgavinm #define	MAX_DIMMNUM	7
56bac58072Sgavinm #define	MAX_CSNUM	7
57bac58072Sgavinm 
587aec1d6eScindi /*
597aec1d6eScindi  * Enumerates the processing chips, or sockets, (as distinct from cores) in a
607aec1d6eScindi  * system.  For each chip found, the necessary nodes (one or more cores, and
617aec1d6eScindi  * possibly a memory controller) are constructed underneath.
627aec1d6eScindi  */
637aec1d6eScindi 
6420c794b3Sgavinm static int chip_enum(topo_mod_t *, tnode_t *, const char *,
6520c794b3Sgavinm     topo_instance_t, topo_instance_t, void *, void *);
668a40a695Sgavinm 
670eb822a1Scindi static const topo_modops_t chip_ops =
680eb822a1Scindi 	{ chip_enum, NULL};
690eb822a1Scindi static const topo_modinfo_t chip_info =
709dd0f810Scindi 	{ CHIP_NODE_NAME, FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops };
710eb822a1Scindi 
720eb822a1Scindi static const topo_pgroup_info_t chip_pgroup =
739dd0f810Scindi 	{ PGNAME(CHIP), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
74e4b86885SCheng Sean Ye 
75e4b86885SCheng Sean Ye static const topo_pgroup_info_t core_pgroup =
76e4b86885SCheng Sean Ye 	{ PGNAME(CORE), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
77e4b86885SCheng Sean Ye 
78e4b86885SCheng Sean Ye static const topo_pgroup_info_t strand_pgroup =
79e4b86885SCheng Sean Ye 	{ PGNAME(STRAND), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
808a40a695Sgavinm 
8120c794b3Sgavinm static const topo_method_t chip_methods[] = {
824557a2a1Srobj 	{ SIMPLE_CHIP_LBL, "Property method", 0,
834557a2a1Srobj 	    TOPO_STABILITY_INTERNAL, simple_chip_label},
844557a2a1Srobj 	{ G4_CHIP_LBL, "Property method", 0,
854557a2a1Srobj 	    TOPO_STABILITY_INTERNAL, g4_chip_label},
862cb5535aSrobj 	{ A4FPLUS_CHIP_LBL, "Property method", 0,
872cb5535aSrobj 	    TOPO_STABILITY_INTERNAL, a4fplus_chip_label},
8864d1d4abSAdrian Frost 	{ FSB2_CHIP_LBL, "Property method", 0,
8964d1d4abSAdrian Frost 	    TOPO_STABILITY_INTERNAL, fsb2_chip_label},
902a613b59SRobert Mustacchi 	{ TOPO_METH_REPLACED, TOPO_METH_REPLACED_DESC,
912a613b59SRobert Mustacchi 	    TOPO_METH_REPLACED_VERSION, TOPO_STABILITY_INTERNAL,
922a613b59SRobert Mustacchi 	    chip_fmri_replaced },
934557a2a1Srobj 	{ NULL }
944557a2a1Srobj };
954557a2a1Srobj 
96e4b86885SCheng Sean Ye static const topo_method_t strands_retire_methods[] = {
97e4b86885SCheng Sean Ye 	{ TOPO_METH_RETIRE, TOPO_METH_RETIRE_DESC,
98e4b86885SCheng Sean Ye 	    TOPO_METH_RETIRE_VERSION, TOPO_STABILITY_INTERNAL,
99e4b86885SCheng Sean Ye 	    retire_strands },
100e4b86885SCheng Sean Ye 	{ TOPO_METH_UNRETIRE, TOPO_METH_UNRETIRE_DESC,
101e4b86885SCheng Sean Ye 	    TOPO_METH_UNRETIRE_VERSION, TOPO_STABILITY_INTERNAL,
102e4b86885SCheng Sean Ye 	    unretire_strands },
103e4b86885SCheng Sean Ye 	{ TOPO_METH_SERVICE_STATE, TOPO_METH_SERVICE_STATE_DESC,
104e4b86885SCheng Sean Ye 	    TOPO_METH_SERVICE_STATE_VERSION, TOPO_STABILITY_INTERNAL,
105e4b86885SCheng Sean Ye 	    service_state_strands },
106e4b86885SCheng Sean Ye 	{ TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC,
107e4b86885SCheng Sean Ye 	    TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL,
108e4b86885SCheng Sean Ye 	    unusable_strands },
109e4b86885SCheng Sean Ye 	{ NULL }
110e4b86885SCheng Sean Ye };
111e4b86885SCheng Sean Ye 
1127aec1d6eScindi int
1137aec1d6eScindi _topo_init(topo_mod_t *mod)
1147aec1d6eScindi {
1150eb822a1Scindi 	if (getenv("TOPOCHIPDBG"))
1160eb822a1Scindi 		topo_mod_setdebug(mod);
1177aec1d6eScindi 	topo_mod_dprintf(mod, "initializing chip enumerator\n");
1187aec1d6eScindi 
1190eb822a1Scindi 	if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
1208a40a695Sgavinm 		whinge(mod, NULL, "failed to register hc: "
1217aec1d6eScindi 		    "%s\n", topo_mod_errmsg(mod));
1227aec1d6eScindi 		return (-1); /* mod errno set */
1237aec1d6eScindi 	}
1247aec1d6eScindi 
1257aec1d6eScindi 	return (0);
1267aec1d6eScindi }
1277aec1d6eScindi 
1287aec1d6eScindi void
1297aec1d6eScindi _topo_fini(topo_mod_t *mod)
1307aec1d6eScindi {
1317aec1d6eScindi 	topo_mod_unregister(mod);
1327aec1d6eScindi }
1337aec1d6eScindi 
134e4b86885SCheng Sean Ye boolean_t
135e4b86885SCheng Sean Ye is_xpv(void)
136e3d60c9bSAdrian Frost {
137e4b86885SCheng Sean Ye 	static int r = -1;
138e4b86885SCheng Sean Ye 	char platform[MAXNAMELEN];
139e3d60c9bSAdrian Frost 
140e4b86885SCheng Sean Ye 	if (r != -1)
141e4b86885SCheng Sean Ye 		return (r == 0);
142e3d60c9bSAdrian Frost 
143e4b86885SCheng Sean Ye 	(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
144e4b86885SCheng Sean Ye 	r = strcmp(platform, "i86xpv");
145e4b86885SCheng Sean Ye 	return (r == 0);
146e4b86885SCheng Sean Ye }
147e3d60c9bSAdrian Frost 
148e4b86885SCheng Sean Ye static tnode_t *
149e4b86885SCheng Sean Ye create_node(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, char *name,
1502a613b59SRobert Mustacchi     topo_instance_t inst, nvlist_t *cpu, uint16_t smbios_id)
151e4b86885SCheng Sean Ye {
152e4b86885SCheng Sean Ye 	nvlist_t *fmri;
153e4b86885SCheng Sean Ye 	tnode_t *cnode;
154e3d60c9bSAdrian Frost 
155e4b86885SCheng Sean Ye 	if (mkrsrc(mod, pnode, name, inst, auth, &fmri) != 0) {
156e4b86885SCheng Sean Ye 		whinge(mod, NULL, "create_node: mkrsrc failed\n");
157e4b86885SCheng Sean Ye 		return (NULL);
158e3d60c9bSAdrian Frost 	}
159074bb90dSTom Pothier 
160074bb90dSTom Pothier 	if (FM_AWARE_SMBIOS(mod)) {
161074bb90dSTom Pothier 		id_t phys_cpu_smbid;
162074bb90dSTom Pothier 		int perr = 0;
163074bb90dSTom Pothier 		const char *serial = NULL;
164074bb90dSTom Pothier 		const char *part = NULL;
165074bb90dSTom Pothier 		const char *rev = NULL;
166074bb90dSTom Pothier 
167074bb90dSTom Pothier 		phys_cpu_smbid = smbios_id;
168074bb90dSTom Pothier 		serial = chip_serial_smbios_get(mod, phys_cpu_smbid);
169074bb90dSTom Pothier 		part = chip_part_smbios_get(mod, phys_cpu_smbid);
170074bb90dSTom Pothier 		rev = chip_rev_smbios_get(mod, phys_cpu_smbid);
171074bb90dSTom Pothier 
172074bb90dSTom Pothier 		perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
173074bb90dSTom Pothier 		    serial);
174074bb90dSTom Pothier 		perr += nvlist_add_string(fmri, FM_FMRI_HC_PART,
175074bb90dSTom Pothier 		    part);
176074bb90dSTom Pothier 		perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION,
177074bb90dSTom Pothier 		    rev);
178074bb90dSTom Pothier 
179074bb90dSTom Pothier 		if (perr != 0)
180074bb90dSTom Pothier 			whinge(mod, NULL,
181074bb90dSTom Pothier 			    "create_node: nvlist_add_string failed\n");
182074bb90dSTom Pothier 
183074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)serial);
184074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)part);
185074bb90dSTom Pothier 		topo_mod_strfree(mod, (char *)rev);
1862a613b59SRobert Mustacchi 	} else {
1872a613b59SRobert Mustacchi 		char *serial = NULL;
1882a613b59SRobert Mustacchi 
1892a613b59SRobert Mustacchi 		if (nvlist_lookup_string(cpu, FM_PHYSCPU_INFO_CHIP_IDENTSTR,
1902a613b59SRobert Mustacchi 		    &serial) == 0) {
1912a613b59SRobert Mustacchi 			if (nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
1922a613b59SRobert Mustacchi 			    serial) != 0) {
1932a613b59SRobert Mustacchi 				whinge(mod, NULL,
1942a613b59SRobert Mustacchi 				    "create_node: nvlist_add_string failed\n");
1952a613b59SRobert Mustacchi 			}
1962a613b59SRobert Mustacchi 		}
197074bb90dSTom Pothier 	}
198074bb90dSTom Pothier 
199e4b86885SCheng Sean Ye 	cnode = topo_node_bind(mod, pnode, name, inst, fmri);
200074bb90dSTom Pothier 
201e4b86885SCheng Sean Ye 	nvlist_free(fmri);
202074bb90dSTom Pothier 	if (cnode == NULL) {
203074bb90dSTom Pothier 		whinge(mod, NULL, "create_node: node bind failed"
204074bb90dSTom Pothier 		    " for %s %d\n", name, (int)inst);
205074bb90dSTom Pothier 	}
206e3d60c9bSAdrian Frost 
207e4b86885SCheng Sean Ye 	return (cnode);
208e3d60c9bSAdrian Frost }
209e3d60c9bSAdrian Frost 
210e3d60c9bSAdrian Frost static int
211074bb90dSTom Pothier create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
212074bb90dSTom Pothier     nvlist_t *auth, uint16_t chip_smbiosid)
213e3d60c9bSAdrian Frost {
214e4b86885SCheng Sean Ye 	tnode_t *strand;
215e4b86885SCheng Sean Ye 	int32_t strandid, cpuid;
216074bb90dSTom Pothier 	int err, perr, nerr = 0;
217e4b86885SCheng Sean Ye 	nvlist_t *fmri;
218074bb90dSTom Pothier 	char *serial = NULL;
219074bb90dSTom Pothier 	char *part = NULL;
220074bb90dSTom Pothier 	char *rev = NULL;
221e3d60c9bSAdrian Frost 
222e4b86885SCheng Sean Ye 	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
223e4b86885SCheng Sean Ye 	    &strandid)) != 0) {
224e4b86885SCheng Sean Ye 		whinge(mod, NULL, "create_strand: lookup strand_id failed: "
225e4b86885SCheng Sean Ye 		    "%s\n", strerror(err));
226e3d60c9bSAdrian Frost 		return (-1);
227e4b86885SCheng Sean Ye 	}
228e3d60c9bSAdrian Frost 
229e4b86885SCheng Sean Ye 	if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid))
230e4b86885SCheng Sean Ye 	    != NULL) {
231e4b86885SCheng Sean Ye 		whinge(mod, NULL, "create_strand: duplicate tuple found\n");
232e4b86885SCheng Sean Ye 		return (-1);
233e4b86885SCheng Sean Ye 	}
234e3d60c9bSAdrian Frost 
235e4b86885SCheng Sean Ye 	if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
2362a613b59SRobert Mustacchi 	    strandid, cpu, chip_smbiosid)) == NULL)
237e4b86885SCheng Sean Ye 		return (-1);
238e3d60c9bSAdrian Frost 
239e4b86885SCheng Sean Ye 	/*
240e4b86885SCheng Sean Ye 	 * Inherit FRU from core node, in native use cpu scheme ASRU,
241e4b86885SCheng Sean Ye 	 * in xpv, use hc scheme ASRU.
242e4b86885SCheng Sean Ye 	 */
243074bb90dSTom Pothier 	(void) topo_node_fru_set(strand, NULL, 0, &perr);
244074bb90dSTom Pothier 	/*
245074bb90dSTom Pothier 	 * From the inherited FRU, extract the Serial
246074bb90dSTom Pothier 	 * number(if SMBIOS donates) and set it in the ASRU
247074bb90dSTom Pothier 	 */
248074bb90dSTom Pothier 	if (FM_AWARE_SMBIOS(mod)) {
249074bb90dSTom Pothier 		char *val = NULL;
250074bb90dSTom Pothier 
251074bb90dSTom Pothier 		if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
252074bb90dSTom Pothier 		    TOPO_PROP_RESOURCE, &fmri, &err) != 0)
253074bb90dSTom Pothier 			whinge(mod, NULL,
254074bb90dSTom Pothier 			    "create_strand: topo_prop_get_fmri failed\n");
255074bb90dSTom Pothier 		if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0)
256074bb90dSTom Pothier 			whinge(mod, NULL,
257074bb90dSTom Pothier 			    "create_strand: nvlist_lookup_string failed: \n");
258074bb90dSTom Pothier 		else
259074bb90dSTom Pothier 			serial = topo_mod_strdup(mod, val);
260074bb90dSTom Pothier 		nvlist_free(fmri);
261074bb90dSTom Pothier 	}
262e4b86885SCheng Sean Ye 	if (is_xpv()) {
263e4b86885SCheng Sean Ye 		if (topo_node_resource(strand, &fmri, &err) == -1) {
264e4b86885SCheng Sean Ye 			whinge(mod, &nerr, "create_strand: "
265e4b86885SCheng Sean Ye 			    "topo_node_resource failed\n");
266e4b86885SCheng Sean Ye 		} else {
267074bb90dSTom Pothier 			if (FM_AWARE_SMBIOS(mod))
268074bb90dSTom Pothier 				(void) nvlist_add_string(fmri,
269074bb90dSTom Pothier 				    FM_FMRI_HC_SERIAL_ID, serial);
270e4b86885SCheng Sean Ye 			(void) topo_node_asru_set(strand, fmri, 0, &err);
271e3d60c9bSAdrian Frost 			nvlist_free(fmri);
272e3d60c9bSAdrian Frost 		}
273e4b86885SCheng Sean Ye 	} else {
274e4b86885SCheng Sean Ye 		if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
275e4b86885SCheng Sean Ye 			whinge(mod, &nerr, "create_strand: lookup cpuid "
276e4b86885SCheng Sean Ye 			    "failed\n");
277e4b86885SCheng Sean Ye 		} else {
278074bb90dSTom Pothier 			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
279e4b86885SCheng Sean Ye 			    != NULL) {
280e4b86885SCheng Sean Ye 				(void) topo_node_asru_set(strand, fmri,
281e4b86885SCheng Sean Ye 				    0, &err);
282e4b86885SCheng Sean Ye 				nvlist_free(fmri);
283e4b86885SCheng Sean Ye 			} else {
284e4b86885SCheng Sean Ye 				whinge(mod, &nerr, "create_strand: "
285e4b86885SCheng Sean Ye 				    "cpu_fmri_create() failed\n");
286e4b86885SCheng Sean Ye 			}
287e4b86885SCheng Sean Ye 		}
288e4b86885SCheng Sean Ye 	}
289e3d60c9bSAdrian Frost 
290e4b86885SCheng Sean Ye 	if (topo_method_register(mod, strand, strands_retire_methods) < 0)
291e4b86885SCheng Sean Ye 		whinge(mod, &nerr, "create_strand: "
292e4b86885SCheng Sean Ye 		    "topo_method_register failed\n");
293e3d60c9bSAdrian Frost 
294e4b86885SCheng Sean Ye 	(void) topo_pgroup_create(strand, &strand_pgroup, &err);
295e4b86885SCheng Sean Ye 	nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
2968031591dSSrihari Venkatesan 	    STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID,
2978031591dSSrihari Venkatesan 	    NULL);
298e3d60c9bSAdrian Frost 
299074bb90dSTom Pothier 	if (FM_AWARE_SMBIOS(mod)) {
300074bb90dSTom Pothier 		(void) topo_node_label_set(strand, NULL, &perr);
301074bb90dSTom Pothier 
302074bb90dSTom Pothier 		if (topo_node_resource(strand, &fmri, &perr) != 0) {
303074bb90dSTom Pothier 			whinge(mod, &nerr, "create_strand: "
304074bb90dSTom Pothier 			    "topo_node_resource failed\n");
305074bb90dSTom Pothier 			perr = 0;
306074bb90dSTom Pothier 		}
307074bb90dSTom Pothier 
308074bb90dSTom Pothier 		perr += nvlist_lookup_string(fmri,
309074bb90dSTom Pothier 		    FM_FMRI_HC_PART, &part);
310074bb90dSTom Pothier 		perr += nvlist_lookup_string(fmri,
311074bb90dSTom Pothier 		    FM_FMRI_HC_REVISION, &rev);
312074bb90dSTom Pothier 
313074bb90dSTom Pothier 		if (perr != 0) {
314074bb90dSTom Pothier 			whinge(mod, NULL,
315074bb90dSTom Pothier 			    "create_strand: nvlist_lookup_string failed\n");
316074bb90dSTom Pothier 			perr = 0;
317074bb90dSTom Pothier 		}
318074bb90dSTom Pothier 
319074bb90dSTom Pothier 		perr += topo_prop_set_string(strand, PGNAME(STRAND),
320074bb90dSTom Pothier 		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
321074bb90dSTom Pothier 		perr += topo_prop_set_string(strand, PGNAME(STRAND),
322074bb90dSTom Pothier 		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
323074bb90dSTom Pothier 		perr += topo_prop_set_string(strand, PGNAME(STRAND),
324074bb90dSTom Pothier 		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
325074bb90dSTom Pothier 
326074bb90dSTom Pothier 		if (perr != 0)
327074bb90dSTom Pothier 			whinge(mod, NULL, "create_strand: topo_prop_set_string"
328074bb90dSTom Pothier 			    "failed\n");
329074bb90dSTom Pothier 
330074bb90dSTom Pothier 		nvlist_free(fmri);
331074bb90dSTom Pothier 		topo_mod_strfree(mod, serial);
332074bb90dSTom Pothier 	}
333074bb90dSTom Pothier 
334e4b86885SCheng Sean Ye 	return (err == 0 && nerr == 0 ? 0 : -1);
335e3d60c9bSAdrian Frost }
336e3d60c9bSAdrian Frost 
3377aec1d6eScindi static int
338074bb90dSTom Pothier create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
339074bb90dSTom Pothier     nvlist_t *auth, uint16_t chip_smbiosid)
3407aec1d6eScindi {
341e4b86885SCheng Sean Ye 	tnode_t *core;
342e4b86885SCheng Sean Ye 	int32_t coreid, cpuid;
343074bb90dSTom Pothier 	int err, perr, nerr = 0;
344e4b86885SCheng Sean Ye 	nvlist_t *fmri;
345074bb90dSTom Pothier 	char *serial = NULL;
346074bb90dSTom Pothier 	char *part = NULL;
347074bb90dSTom Pothier 	char *rev = NULL;
3487aec1d6eScindi 
349e4b86885SCheng Sean Ye 	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
350e4b86885SCheng Sean Ye 	    != 0) {
351e4b86885SCheng Sean Ye 		whinge(mod, NULL, "create_core: lookup core_id failed: %s\n",
352e4b86885SCheng Sean Ye 		    strerror(err));
3537aec1d6eScindi 		return (-1);
354e4b86885SCheng Sean Ye 	}
355e4b86885SCheng Sean Ye 	if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
356e4b86885SCheng Sean Ye 		if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
3572a613b59SRobert Mustacchi 		    coreid, cpu, chip_smbiosid)) == NULL)
358e4b86885SCheng Sean Ye 			return (-1);
3597aec1d6eScindi 
3608a40a695Sgavinm 		/*
361e4b86885SCheng Sean Ye 		 * Inherit FRU from the chip node, for native, we use hc
362e4b86885SCheng Sean Ye 		 * scheme ASRU for the core node.
3638a40a695Sgavinm 		 */
364074bb90dSTom Pothier 		(void) topo_node_fru_set(core, NULL, 0, &perr);
365074bb90dSTom Pothier 		/*
366074bb90dSTom Pothier 		 * From the inherited FRU, extract the Serial
367074bb90dSTom Pothier 		 * number if SMBIOS donates and set it in the ASRU
368074bb90dSTom Pothier 		 */
369074bb90dSTom Pothier 		if (FM_AWARE_SMBIOS(mod)) {
370074bb90dSTom Pothier 			char *val = NULL;
371074bb90dSTom Pothier 
372074bb90dSTom Pothier 			if (topo_node_resource(core, &fmri, &err) != 0)
373074bb90dSTom Pothier 				whinge(mod, NULL,
374074bb90dSTom Pothier 				    "create_core: topo_prop_get_fmri failed\n");
375074bb90dSTom Pothier 			if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID,
376074bb90dSTom Pothier 			    &val) != 0)
377074bb90dSTom Pothier 				whinge(mod, NULL, "create_core:"
378074bb90dSTom Pothier 				    "nvlist_lookup_string failed\n");
379074bb90dSTom Pothier 			else
380074bb90dSTom Pothier 				serial = topo_mod_strdup(mod, val);
381074bb90dSTom Pothier 			nvlist_free(fmri);
382074bb90dSTom Pothier 		}
383e4b86885SCheng Sean Ye 		if (is_xpv()) {
384e4b86885SCheng Sean Ye 			if (topo_node_resource(core, &fmri, &err) == -1) {
385e4b86885SCheng Sean Ye 				whinge(mod, &nerr, "create_core: "
386e4b86885SCheng Sean Ye 				    "topo_node_resource failed\n");
387e4b86885SCheng Sean Ye 			} else {
388074bb90dSTom Pothier 				if (FM_AWARE_SMBIOS(mod))
389074bb90dSTom Pothier 					(void) nvlist_add_string(fmri,
390074bb90dSTom Pothier 					    FM_FMRI_HC_SERIAL_ID, serial);
391e4b86885SCheng Sean Ye 				(void) topo_node_asru_set(core, fmri, 0, &err);
392e4b86885SCheng Sean Ye 				nvlist_free(fmri);
393e4b86885SCheng Sean Ye 			}
3947aec1d6eScindi 		}
395e4b86885SCheng Sean Ye 		if (topo_method_register(mod, core, strands_retire_methods) < 0)
396e4b86885SCheng Sean Ye 			whinge(mod, &nerr, "create_core: "
397e4b86885SCheng Sean Ye 			    "topo_method_register failed\n");
398e4b86885SCheng Sean Ye 
399e4b86885SCheng Sean Ye 		(void) topo_pgroup_create(core, &core_pgroup, &err);
4008031591dSSrihari Venkatesan 		nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL,
4018031591dSSrihari Venkatesan 		    CORE_CHIP_ID, CORE_PROCNODE_ID, NULL);
4027aec1d6eScindi 
403e4b86885SCheng Sean Ye 		if (topo_node_range_create(mod, core, STRAND_NODE_NAME,
404e4b86885SCheng Sean Ye 		    0, 255) != 0)
405e4b86885SCheng Sean Ye 			return (-1);
406*f2dbfd32SRobert Mustacchi 
407*f2dbfd32SRobert Mustacchi 		/*
408*f2dbfd32SRobert Mustacchi 		 * Creating a temperature sensor may fail because the sensor
409*f2dbfd32SRobert Mustacchi 		 * doesn't exist or due to internal reasons. At the moment, we
410*f2dbfd32SRobert Mustacchi 		 * swallow any such errors that occur.
411*f2dbfd32SRobert Mustacchi 		 */
412*f2dbfd32SRobert Mustacchi 		(void) chip_create_core_temp_sensor(mod, core);
413e4b86885SCheng Sean Ye 	}
4148a40a695Sgavinm 
415074bb90dSTom Pothier 	if (!is_xpv()) {
4168a40a695Sgavinm 		/*
417e4b86885SCheng Sean Ye 		 * In native mode, we're in favor of cpu scheme ASRU for
418e4b86885SCheng Sean Ye 		 * printing reason.  More work needs to be done to support
419e4b86885SCheng Sean Ye 		 * multi-strand cpu: the ASRU will be a list of cpuid then.
4208a40a695Sgavinm 		 */
421e4b86885SCheng Sean Ye 		if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
422e4b86885SCheng Sean Ye 			whinge(mod, &nerr, "create_core: lookup cpuid "
4238a40a695Sgavinm 			    "failed\n");
424e4b86885SCheng Sean Ye 		} else {
425074bb90dSTom Pothier 			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
426e4b86885SCheng Sean Ye 			    != NULL) {
427e4b86885SCheng Sean Ye 				(void) topo_node_asru_set(core, fmri, 0, &err);
428e4b86885SCheng Sean Ye 				nvlist_free(fmri);
429e4b86885SCheng Sean Ye 			} else {
430e4b86885SCheng Sean Ye 				whinge(mod, &nerr, "create_core: "
431e4b86885SCheng Sean Ye 				    "cpu_fmri_create() failed\n");
432e4b86885SCheng Sean Ye 			}
4337aec1d6eScindi 		}
4347aec1d6eScindi 	}
4357aec1d6eScindi 
436074bb90dSTom Pothier 	if (FM_AWARE_SMBIOS(mod)) {
437074bb90dSTom Pothier 		(void) topo_node_label_set(core, NULL, &perr);
438074bb90dSTom Pothier 
439074bb90dSTom Pothier 		if (topo_node_resource(core, &fmri, &perr) != 0) {
440074bb90dSTom Pothier 			whinge(mod, &nerr, "create_core: "
441074bb90dSTom Pothier 			    "topo_node_resource failed\n");
442074bb90dSTom Pothier 			perr = 0;
443074bb90dSTom Pothier 		}
444074bb90dSTom Pothier 
445074bb90dSTom Pothier 		perr += nvlist_lookup_string(fmri,
446074bb90dSTom Pothier 		    FM_FMRI_HC_PART, &part);
447074bb90dSTom Pothier 		perr += nvlist_lookup_string(fmri,
448074bb90dSTom Pothier 		    FM_FMRI_HC_REVISION, &rev);
449074bb90dSTom Pothier 
450074bb90dSTom Pothier 		if (perr != 0) {
451074bb90dSTom Pothier 			whinge(mod, NULL,
452074bb90dSTom Pothier 			    "create_core: nvlist_lookup_string failed\n");
453074bb90dSTom Pothier 			perr = 0;
454074bb90dSTom Pothier 		}
455074bb90dSTom Pothier 
456074bb90dSTom Pothier 		perr += topo_prop_set_string(core, PGNAME(CORE),
457074bb90dSTom Pothier 		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
458074bb90dSTom Pothier 		perr += topo_prop_set_string(core, PGNAME(CORE),
459074bb90dSTom Pothier 		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
460074bb90dSTom Pothier 		perr += topo_prop_set_string(core, PGNAME(CORE),
461074bb90dSTom Pothier 		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
462074bb90dSTom Pothier 
463074bb90dSTom Pothier 		if (perr != 0)
464074bb90dSTom Pothier 			whinge(mod, NULL, "create_core: topo_prop_set_string"
465074bb90dSTom Pothier 			    "failed\n");
466074bb90dSTom Pothier 
467074bb90dSTom Pothier 		nvlist_free(fmri);
468074bb90dSTom Pothier 		topo_mod_strfree(mod, serial);
469074bb90dSTom Pothier 	}
470074bb90dSTom Pothier 
471074bb90dSTom Pothier 	err = create_strand(mod, core, cpu, auth, chip_smbiosid);
472e4b86885SCheng Sean Ye 
473e4b86885SCheng Sean Ye 	return (err == 0 && nerr == 0 ? 0 : -1);
4747aec1d6eScindi }
4757aec1d6eScindi 
4767aec1d6eScindi static int
477e4b86885SCheng Sean Ye create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
478e4b86885SCheng Sean Ye     topo_instance_t max, nvlist_t *cpu, nvlist_t *auth,
479c26bf377SRob Johnston     int mc_offchip, kstat_ctl_t *kc)
4807aec1d6eScindi {
481e4b86885SCheng Sean Ye 	tnode_t *chip;
482e4b86885SCheng Sean Ye 	nvlist_t *fmri = NULL;
483074bb90dSTom Pothier 	int err, perr, nerr = 0;
4848031591dSSrihari Venkatesan 	int32_t chipid, procnodeid, procnodes_per_pkg;
485c26bf377SRob Johnston 	const char *vendor, *brand;
4868031591dSSrihari Venkatesan 	int32_t family, model;
487c93c462eSCheng Sean Ye 	boolean_t create_mc = B_FALSE;
488074bb90dSTom Pothier 	uint16_t smbios_id;
4897aec1d6eScindi 
490074bb90dSTom Pothier 	/*
491074bb90dSTom Pothier 	 * /dev/fm will export the chipid based on SMBIOS' ordering
492074bb90dSTom Pothier 	 * of Type-4 structures, if SMBIOS meets FMA needs
493074bb90dSTom Pothier 	 */
4948031591dSSrihari Venkatesan 	err = nvlist_lookup_pairs(cpu, 0,
4958031591dSSrihari Venkatesan 	    FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32, &chipid,
4968031591dSSrihari Venkatesan 	    FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32, &procnodes_per_pkg,
4978031591dSSrihari Venkatesan 	    FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32, &procnodeid,
4988031591dSSrihari Venkatesan 	    FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING, &vendor,
4998031591dSSrihari Venkatesan 	    FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32, &family,
5008031591dSSrihari Venkatesan 	    FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32, &model,
5018031591dSSrihari Venkatesan 	    NULL);
5028031591dSSrihari Venkatesan 
5038031591dSSrihari Venkatesan 	if (err) {
5048031591dSSrihari Venkatesan 		whinge(mod, NULL, "create_chip: lookup failed: %s\n",
505e4b86885SCheng Sean Ye 		    strerror(err));
506e4b86885SCheng Sean Ye 		return (-1);
5077aec1d6eScindi 	}
5087aec1d6eScindi 
509e4b86885SCheng Sean Ye 	if (chipid < min || chipid > max)
510e4b86885SCheng Sean Ye 		return (-1);
5117aec1d6eScindi 
512074bb90dSTom Pothier 	if (FM_AWARE_SMBIOS(mod)) {
513074bb90dSTom Pothier 		if ((err = nvlist_lookup_uint16(cpu,
514074bb90dSTom Pothier 		    FM_PHYSCPU_INFO_SMBIOS_ID, &smbios_id)) != 0) {
515074bb90dSTom Pothier 			whinge(mod, NULL,
516074bb90dSTom Pothier 			    "create_chip: lookup smbios_id failed"
517074bb90dSTom Pothier 			    ": enumerating x86pi & chip topology, but"
518074bb90dSTom Pothier 			    " no Chip properties from SMBIOS"
519074bb90dSTom Pothier 			    " - err msg : %s\n", strerror(err));
520074bb90dSTom Pothier 			/*
521074bb90dSTom Pothier 			 * Lets reset the module specific
522074bb90dSTom Pothier 			 * data to NULL, overriding any
523074bb90dSTom Pothier 			 * SMBIOS capability encoded earlier.
524074bb90dSTom Pothier 			 * This will fail all subsequent
525074bb90dSTom Pothier 			 * FM_AWARE_SMBIOS checks.
526074bb90dSTom Pothier 			 */
527074bb90dSTom Pothier 			topo_mod_setspecific(mod, NULL);
528074bb90dSTom Pothier 		}
529074bb90dSTom Pothier 	}
530074bb90dSTom Pothier 
531e4b86885SCheng Sean Ye 	if ((chip = topo_node_lookup(pnode, CHIP_NODE_NAME, chipid)) == NULL) {
532e4b86885SCheng Sean Ye 		if ((chip = create_node(mod, pnode, auth, CHIP_NODE_NAME,
5332a613b59SRobert Mustacchi 		    chipid, cpu, smbios_id)) == NULL)
534e4b86885SCheng Sean Ye 			return (-1);
535074bb90dSTom Pothier 		/*
536074bb90dSTom Pothier 		 * Do not register XML map methods if SMBIOS can provide
537074bb90dSTom Pothier 		 * serial, part, revision & label
538074bb90dSTom Pothier 		 */
539074bb90dSTom Pothier 		if (!FM_AWARE_SMBIOS(mod)) {
540074bb90dSTom Pothier 			if (topo_method_register(mod, chip, chip_methods) < 0)
541074bb90dSTom Pothier 				whinge(mod, &nerr, "create_chip: "
542074bb90dSTom Pothier 				    "topo_method_register failed\n");
5437aec1d6eScindi 		}
5447aec1d6eScindi 
545e4b86885SCheng Sean Ye 		(void) topo_pgroup_create(chip, &chip_pgroup, &err);
546e4b86885SCheng Sean Ye 		nerr -= add_nvlist_strprop(mod, chip, cpu, PGNAME(CHIP),
5478031591dSSrihari Venkatesan 		    CHIP_VENDOR_ID, NULL);
548e4b86885SCheng Sean Ye 		nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP),
5498031591dSSrihari Venkatesan 		    NULL, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL);
5504557a2a1Srobj 
551c26bf377SRob Johnston 		/*
552c26bf377SRob Johnston 		 * Attempt to lookup the processor brand string in kstats.
553c26bf377SRob Johnston 		 * and add it as a prop, if found.
554c26bf377SRob Johnston 		 */
555c26bf377SRob Johnston 		brand = get_chip_brand(mod, kc, chipid);
556c26bf377SRob Johnston 		if (brand != NULL && topo_prop_set_string(chip, PGNAME(CHIP),
557c26bf377SRob Johnston 		    CHIP_BRAND, TOPO_PROP_IMMUTABLE, brand, &perr) != 0) {
558c26bf377SRob Johnston 			whinge(mod, &nerr, "failed to set prop %s/%s",
559c26bf377SRob Johnston 			    PGNAME(CHIP), CHIP_BRAND);
560c26bf377SRob Johnston 		}
561c26bf377SRob Johnston 		topo_mod_strfree(mod, (char *)brand);
562c26bf377SRob Johnston 
563074bb90dSTom Pothier 		if (FM_AWARE_SMBIOS(mod)) {
564074bb90dSTom Pothier 			int fru = 0;
565074bb90dSTom Pothier 			char *serial = NULL;
566074bb90dSTom Pothier 			char *part = NULL;
567074bb90dSTom Pothier 			char *rev = NULL;
568074bb90dSTom Pothier 			char *label;
569074bb90dSTom Pothier 
570074bb90dSTom Pothier 			fru = chip_fru_smbios_get(mod, smbios_id);
571074bb90dSTom Pothier 			/*
572074bb90dSTom Pothier 			 * Chip is not a FRU, set the FRU fmri of parent node
573074bb90dSTom Pothier 			 */
574074bb90dSTom Pothier 			if (topo_node_resource(chip, &fmri, &perr) != 0)
575074bb90dSTom Pothier 				whinge(mod, &nerr, "create_chip: "
576074bb90dSTom Pothier 				    "topo_node_resource failed\n");
577074bb90dSTom Pothier 			if (!fru) {
578074bb90dSTom Pothier 				(void) topo_node_fru_set(chip, NULL, 0, &perr);
579074bb90dSTom Pothier 				label = NULL;
580074bb90dSTom Pothier 			} else {
581074bb90dSTom Pothier 				label = (char *)chip_label_smbios_get(mod,
582074bb90dSTom Pothier 				    pnode, smbios_id, NULL);
583074bb90dSTom Pothier 
584074bb90dSTom Pothier 				if (topo_node_fru_set(chip, fmri, 0, &perr)
585074bb90dSTom Pothier 				    != 0) {
586074bb90dSTom Pothier 					whinge(mod, NULL, "create_chip: "
587074bb90dSTom Pothier 					    "topo_node_fru_set failed\n");
588074bb90dSTom Pothier 					perr = 0;
589074bb90dSTom Pothier 				}
590074bb90dSTom Pothier 			}
591074bb90dSTom Pothier 
592074bb90dSTom Pothier 			perr += nvlist_lookup_string(fmri,
593074bb90dSTom Pothier 			    FM_FMRI_HC_SERIAL_ID, &serial);
594074bb90dSTom Pothier 			perr += nvlist_lookup_string(fmri,
595074bb90dSTom Pothier 			    FM_FMRI_HC_PART, &part);
596074bb90dSTom Pothier 			perr += nvlist_lookup_string(fmri,
597074bb90dSTom Pothier 			    FM_FMRI_HC_REVISION, &rev);
598074bb90dSTom Pothier 
599074bb90dSTom Pothier 			if (perr != 0) {
600074bb90dSTom Pothier 				whinge(mod, NULL,
601074bb90dSTom Pothier 				    "create_chip: nvlist_lookup_string"
602074bb90dSTom Pothier 				    "failed\n");
603074bb90dSTom Pothier 				perr = 0;
604074bb90dSTom Pothier 			}
605074bb90dSTom Pothier 
606074bb90dSTom Pothier 			perr += topo_prop_set_string(chip, PGNAME(CHIP),
607074bb90dSTom Pothier 			    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
608074bb90dSTom Pothier 			    serial, &perr);
609074bb90dSTom Pothier 			perr += topo_prop_set_string(chip, PGNAME(CHIP),
610074bb90dSTom Pothier 			    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
611074bb90dSTom Pothier 			    part, &perr);
612074bb90dSTom Pothier 			perr += topo_prop_set_string(chip, PGNAME(CHIP),
613074bb90dSTom Pothier 			    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
614074bb90dSTom Pothier 			    rev, &perr);
615074bb90dSTom Pothier 
616074bb90dSTom Pothier 			if (perr != 0)
617074bb90dSTom Pothier 				whinge(mod, NULL,
618074bb90dSTom Pothier 				    "create_chip: topo_prop_set_string"
619074bb90dSTom Pothier 				    "failed\n");
620074bb90dSTom Pothier 
621074bb90dSTom Pothier 			nvlist_free(fmri);
622074bb90dSTom Pothier 
623074bb90dSTom Pothier 			if (topo_node_label_set(chip, label, &perr)
624074bb90dSTom Pothier 			    == -1) {
625074bb90dSTom Pothier 				whinge(mod, NULL, "create_chip: "
626074bb90dSTom Pothier 				    "topo_node_label_set failed\n");
627074bb90dSTom Pothier 			}
628074bb90dSTom Pothier 			topo_mod_strfree(mod, label);
629074bb90dSTom Pothier 
630074bb90dSTom Pothier 		} else {
631074bb90dSTom Pothier 			if (topo_node_resource(chip, &fmri, &err) == -1) {
632074bb90dSTom Pothier 				whinge(mod, &nerr, "create_chip: "
633074bb90dSTom Pothier 				    "topo_node_resource failed\n");
634074bb90dSTom Pothier 			} else {
635074bb90dSTom Pothier 				(void) topo_node_fru_set(chip, fmri, 0, &perr);
636074bb90dSTom Pothier 				nvlist_free(fmri);
637074bb90dSTom Pothier 			}
638074bb90dSTom Pothier 		}
639074bb90dSTom Pothier 
640e4b86885SCheng Sean Ye 		if (topo_method_register(mod, chip, strands_retire_methods) < 0)
641e4b86885SCheng Sean Ye 			whinge(mod, &nerr, "create_chip: "
642e4b86885SCheng Sean Ye 			    "topo_method_register failed\n");
6437aec1d6eScindi 
6448031591dSSrihari Venkatesan 		if (topo_node_range_create(mod, chip, CORE_NODE_NAME, 0, 255))
645e4b86885SCheng Sean Ye 			return (-1);
646c93c462eSCheng Sean Ye 
6478031591dSSrihari Venkatesan 		if (strcmp(vendor, "AuthenticAMD") == 0) {
6488031591dSSrihari Venkatesan 			if (topo_node_range_create(mod, chip, MCT_NODE_NAME,
6498031591dSSrihari Venkatesan 			    0, 255))
6508031591dSSrihari Venkatesan 				return (-1);
6518031591dSSrihari Venkatesan 		}
6528031591dSSrihari Venkatesan 
653c93c462eSCheng Sean Ye 		create_mc = B_TRUE;
654*f2dbfd32SRobert Mustacchi 
655*f2dbfd32SRobert Mustacchi 		/*
656*f2dbfd32SRobert Mustacchi 		 * Creating a temperature sensor may fail because the sensor
657*f2dbfd32SRobert Mustacchi 		 * doesn't exist or due to internal reasons. At the moment, we
658*f2dbfd32SRobert Mustacchi 		 * swallow any such errors that occur.
659*f2dbfd32SRobert Mustacchi 		 */
660*f2dbfd32SRobert Mustacchi 		(void) chip_create_chip_temp_sensor(mod, chip);
661e4b86885SCheng Sean Ye 	}
6627aec1d6eScindi 
663074bb90dSTom Pothier 	if (FM_AWARE_SMBIOS(mod)) {
664074bb90dSTom Pothier 		int status = 0;
665074bb90dSTom Pothier 		/*
666074bb90dSTom Pothier 		 * STATUS
667074bb90dSTom Pothier 		 * CPU Socket Populated
668074bb90dSTom Pothier 		 * CPU Socket Unpopulated
669074bb90dSTom Pothier 		 * Populated : Enabled
670074bb90dSTom Pothier 		 * Populated : Disabled by BIOS (Setup)
671074bb90dSTom Pothier 		 * Populated : Disabled by BIOS (Error)
672074bb90dSTom Pothier 		 * Populated : Idle
673074bb90dSTom Pothier 		 *
674074bb90dSTom Pothier 		 * Enumerate core & strand only for Populated : Enabled
675074bb90dSTom Pothier 		 * Enumerate Off-Chip Memory Controller only for
676074bb90dSTom Pothier 		 * Populated : Enabled
677074bb90dSTom Pothier 		 */
678074bb90dSTom Pothier 
679074bb90dSTom Pothier 		status = chip_status_smbios_get(mod, (id_t)smbios_id);
680074bb90dSTom Pothier 		if (!status) {
681074bb90dSTom Pothier 			whinge(mod, NULL, "create_chip: "
682074bb90dSTom Pothier 			    "CPU Socket is not populated or is disabled\n");
683074bb90dSTom Pothier 			return (0);
684074bb90dSTom Pothier 		}
685074bb90dSTom Pothier 	}
686074bb90dSTom Pothier 
687074bb90dSTom Pothier 	err = create_core(mod, chip, cpu, auth, smbios_id);
6889dd0f810Scindi 
689e4b86885SCheng Sean Ye 	/*
690e4b86885SCheng Sean Ye 	 * Create memory-controller node under a chip for architectures
691e4b86885SCheng Sean Ye 	 * that may have on-chip memory-controller(s).
692074bb90dSTom Pothier 	 * If SMBIOS meets FMA needs, when Multi-Chip-Module is
693074bb90dSTom Pothier 	 * addressed, mc instances should be derived from SMBIOS
694e4b86885SCheng Sean Ye 	 */
6958031591dSSrihari Venkatesan 	if (strcmp(vendor, "AuthenticAMD") == 0) {
6968031591dSSrihari Venkatesan 		amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth,
6978031591dSSrihari Venkatesan 		    procnodeid, procnodes_per_pkg, family, model, &nerr);
6988031591dSSrihari Venkatesan 	} else if (create_mc && !mc_offchip)
6998031591dSSrihari Venkatesan 		onchip_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth);
7007aec1d6eScindi 
701e4b86885SCheng Sean Ye 	return (err == 0 && nerr == 0 ? 0 : -1);
702e4b86885SCheng Sean Ye }
703e3d60c9bSAdrian Frost 
704e4b86885SCheng Sean Ye /*ARGSUSED*/
705e4b86885SCheng Sean Ye static int
706e4b86885SCheng Sean Ye create_chips(topo_mod_t *mod, tnode_t *pnode, const char *name,
707e4b86885SCheng Sean Ye     topo_instance_t min, topo_instance_t max, void *arg, nvlist_t *auth,
708e4b86885SCheng Sean Ye     int mc_offchip)
709e4b86885SCheng Sean Ye {
710e4b86885SCheng Sean Ye 	fmd_agent_hdl_t *hdl;
711e4b86885SCheng Sean Ye 	nvlist_t **cpus;
712e4b86885SCheng Sean Ye 	int nerr = 0;
713e4b86885SCheng Sean Ye 	uint_t i, ncpu;
714c26bf377SRob Johnston 	kstat_ctl_t *kc;
71520c794b3Sgavinm 
716e4b86885SCheng Sean Ye 	if (strcmp(name, CHIP_NODE_NAME) != 0)
717e4b86885SCheng Sean Ye 		return (0);
718e4b86885SCheng Sean Ye 
719e4b86885SCheng Sean Ye 	if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL)
720e4b86885SCheng Sean Ye 		return (-1);
721e4b86885SCheng Sean Ye 	if (fmd_agent_physcpu_info(hdl, &cpus, &ncpu) != 0) {
722e4b86885SCheng Sean Ye 		whinge(mod, NULL, "create_chip: fmd_agent_physcpu_info "
723e4b86885SCheng Sean Ye 		    "failed: %s\n", fmd_agent_errmsg(hdl));
724e4b86885SCheng Sean Ye 		fmd_agent_close(hdl);
725e4b86885SCheng Sean Ye 		return (-1);
7267aec1d6eScindi 	}
727e4b86885SCheng Sean Ye 	fmd_agent_close(hdl);
7287aec1d6eScindi 
729c26bf377SRob Johnston 	if ((kc = kstat_open()) == NULL) {
730c26bf377SRob Johnston 		whinge(mod, NULL, "kstat_open() failed");
731c26bf377SRob Johnston 		return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
732c26bf377SRob Johnston 	}
733c26bf377SRob Johnston 
734e4b86885SCheng Sean Ye 	for (i = 0; i < ncpu; i++) {
735e4b86885SCheng Sean Ye 		nerr -= create_chip(mod, pnode, min, max, cpus[i], auth,
736c26bf377SRob Johnston 		    mc_offchip, kc);
737e4b86885SCheng Sean Ye 		nvlist_free(cpus[i]);
738e4b86885SCheng Sean Ye 	}
739c26bf377SRob Johnston 	(void) kstat_close(kc);
740e4b86885SCheng Sean Ye 	umem_free(cpus, sizeof (nvlist_t *) * ncpu);
7417aec1d6eScindi 
7428a40a695Sgavinm 	if (nerr == 0) {
7438a40a695Sgavinm 		return (0);
7448a40a695Sgavinm 	} else {
7457aec1d6eScindi 		(void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
7468a40a695Sgavinm 		return (-1);
7478a40a695Sgavinm 	}
7487aec1d6eScindi }
7497aec1d6eScindi 
7500eb822a1Scindi /*ARGSUSED*/
7517aec1d6eScindi static int
7527aec1d6eScindi chip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
753074bb90dSTom Pothier     topo_instance_t min, topo_instance_t max, void *arg, void *smbios_enabled)
7547aec1d6eScindi {
7550eb822a1Scindi 	int rv = 0;
7560eb822a1Scindi 	nvlist_t *auth = NULL;
757e3d60c9bSAdrian Frost 	int offchip_mc;
758e4b86885SCheng Sean Ye 	char buf[BUFSIZ];
759e4b86885SCheng Sean Ye 	const char *dom0 = "control_d";
760e4b86885SCheng Sean Ye 
761e4b86885SCheng Sean Ye 	/*
762e4b86885SCheng Sean Ye 	 * Create nothing if we're running in domU.
763e4b86885SCheng Sean Ye 	 */
764e4b86885SCheng Sean Ye 	if (sysinfo(SI_PLATFORM, buf, sizeof (buf)) == -1)
765e4b86885SCheng Sean Ye 		return (-1);
766e4b86885SCheng Sean Ye 
767e4b86885SCheng Sean Ye 	if (strncmp(buf, "i86pc", sizeof (buf)) != 0 &&
768e4b86885SCheng Sean Ye 	    strncmp(buf, "i86xpv", sizeof (buf)) != 0)
769e4b86885SCheng Sean Ye 		return (0);
770e4b86885SCheng Sean Ye 
771e4b86885SCheng Sean Ye 	if (strncmp(buf, "i86xpv", sizeof (buf)) == 0) {
772e4b86885SCheng Sean Ye 		int fd = open("/dev/xen/domcaps", O_RDONLY);
773e4b86885SCheng Sean Ye 
774e4b86885SCheng Sean Ye 		if (fd != -1) {
775e4b86885SCheng Sean Ye 			if (read(fd, buf, sizeof (buf)) <= 0 ||
776e4b86885SCheng Sean Ye 			    strncmp(buf, dom0, strlen(dom0)) != 0) {
777e4b86885SCheng Sean Ye 				(void) close(fd);
778e4b86885SCheng Sean Ye 				return (0);
779e4b86885SCheng Sean Ye 			}
780e4b86885SCheng Sean Ye 			(void) close(fd);
781e4b86885SCheng Sean Ye 		}
782e4b86885SCheng Sean Ye 	}
7830eb822a1Scindi 
784074bb90dSTom Pothier 	/*
785074bb90dSTom Pothier 	 * Set Chip Enumerator Module's private data with the value passed by
786074bb90dSTom Pothier 	 * x86pi Enumerator, defining SMBIOS capabilities
787074bb90dSTom Pothier 	 */
788074bb90dSTom Pothier 	topo_mod_setspecific(mod, smbios_enabled);
789074bb90dSTom Pothier 
790074bb90dSTom Pothier 	if (FM_AWARE_SMBIOS(mod))
791074bb90dSTom Pothier 		if (init_chip_smbios(mod) != 0) {
792074bb90dSTom Pothier 			whinge(mod, NULL,
793074bb90dSTom Pothier 			    "init_chip_smbios() failed, "
794074bb90dSTom Pothier 			    " enumerating x86pi & chip topology, but no"
795074bb90dSTom Pothier 			    " CPU & Memory properties will be"
796074bb90dSTom Pothier 			    " derived from SMBIOS\n");
797074bb90dSTom Pothier 			/*
798074bb90dSTom Pothier 			 * Lets reset the module specific
799074bb90dSTom Pothier 			 * data to NULL, overriding any
800074bb90dSTom Pothier 			 * SMBIOS capability encoded earlier.
801074bb90dSTom Pothier 			 * This will fail all subsequent
802074bb90dSTom Pothier 			 * FM_AWARE_SMBIOS checks.
803074bb90dSTom Pothier 			 */
804074bb90dSTom Pothier 			topo_mod_setspecific(mod, NULL);
805074bb90dSTom Pothier 		}
806074bb90dSTom Pothier 
8070eb822a1Scindi 	auth = topo_mod_auth(mod, pnode);
8087aec1d6eScindi 
809e3d60c9bSAdrian Frost 	offchip_mc = mc_offchip_open();
8109dd0f810Scindi 	if (strcmp(name, CHIP_NODE_NAME) == 0)
811e4b86885SCheng Sean Ye 		rv = create_chips(mod, pnode, name, min, max, NULL, auth,
812e3d60c9bSAdrian Frost 		    offchip_mc);
8137aec1d6eScindi 
814e3d60c9bSAdrian Frost 	if (offchip_mc)
81520c794b3Sgavinm 		(void) mc_offchip_create(mod, pnode, "memory-controller", auth);
81620c794b3Sgavinm 
8170eb822a1Scindi 	nvlist_free(auth);
8180eb822a1Scindi 
8190eb822a1Scindi 	return (rv);
8207aec1d6eScindi }
821