1dd23d762SRobert Mustacchi /*
2dd23d762SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3dd23d762SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4dd23d762SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5dd23d762SRobert Mustacchi  * 1.0 of the CDDL.
6dd23d762SRobert Mustacchi  *
7dd23d762SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8dd23d762SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9dd23d762SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10dd23d762SRobert Mustacchi  */
11dd23d762SRobert Mustacchi 
12dd23d762SRobert Mustacchi /*
13*019df03dSRobert Mustacchi  * Copyright 2024 Oxide Computer Company
14dd23d762SRobert Mustacchi  */
15dd23d762SRobert Mustacchi 
16dd23d762SRobert Mustacchi /*
17dd23d762SRobert Mustacchi  * This file is focused upon building up the tree of information that we need to
18dd23d762SRobert Mustacchi  * build the module's various topology nodes as well as any methods that need to
19dd23d762SRobert Mustacchi  * operate on them.
20dd23d762SRobert Mustacchi  */
21dd23d762SRobert Mustacchi 
22dd23d762SRobert Mustacchi #include <sys/fm/protocol.h>
23dd23d762SRobert Mustacchi #include <fm/topo_hc.h>
24dd23d762SRobert Mustacchi #include <sys/devfm.h>
25dd23d762SRobert Mustacchi #include <assert.h>
26dd23d762SRobert Mustacchi 
27dd23d762SRobert Mustacchi #include "topo_zen_impl.h"
28dd23d762SRobert Mustacchi 
29dd23d762SRobert Mustacchi static const topo_pgroup_info_t topo_zen_chip_pgroup = {
30dd23d762SRobert Mustacchi 	TOPO_PGROUP_CHIP,
31dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
32dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
33dd23d762SRobert Mustacchi 	1
34dd23d762SRobert Mustacchi };
35dd23d762SRobert Mustacchi 
36dd23d762SRobert Mustacchi static const topo_pgroup_info_t topo_zen_ccd_pgroup = {
37dd23d762SRobert Mustacchi 	TOPO_PGROUP_CCD,
38dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
39dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
40dd23d762SRobert Mustacchi 	1
41dd23d762SRobert Mustacchi };
42dd23d762SRobert Mustacchi 
43dd23d762SRobert Mustacchi static const topo_pgroup_info_t topo_zen_ccx_pgroup = {
44dd23d762SRobert Mustacchi 	TOPO_PGROUP_CCX,
45dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
46dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
47dd23d762SRobert Mustacchi 	1
48dd23d762SRobert Mustacchi };
49dd23d762SRobert Mustacchi 
50dd23d762SRobert Mustacchi static const topo_pgroup_info_t topo_zen_core_pgroup = {
51dd23d762SRobert Mustacchi 	TOPO_PGROUP_CORE,
52dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
53dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
54dd23d762SRobert Mustacchi 	1
55dd23d762SRobert Mustacchi };
56dd23d762SRobert Mustacchi 
57dd23d762SRobert Mustacchi static const topo_pgroup_info_t topo_zen_strand_pgroup = {
58dd23d762SRobert Mustacchi 	TOPO_PGROUP_STRAND,
59dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
60dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
61dd23d762SRobert Mustacchi 	1
62dd23d762SRobert Mustacchi };
63dd23d762SRobert Mustacchi 
64dd23d762SRobert Mustacchi static const topo_pgroup_info_t topo_zen_cache_pgroup = {
65dd23d762SRobert Mustacchi 	TOPO_PGROUP_CACHE,
66dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
67dd23d762SRobert Mustacchi 	TOPO_STABILITY_PRIVATE,
68dd23d762SRobert Mustacchi 	1
69dd23d762SRobert Mustacchi };
70dd23d762SRobert Mustacchi 
71dd23d762SRobert Mustacchi /*
72dd23d762SRobert Mustacchi  * Common interface to create a topo node in our socket and bind it to its
73dd23d762SRobert Mustacchi  * parent. The following properties are commonly shared between all nodes in the
74dd23d762SRobert Mustacchi  * chip:
75dd23d762SRobert Mustacchi  *
76dd23d762SRobert Mustacchi  * o The serial and revision are part of the FMRI. We don't have a good way to
77dd23d762SRobert Mustacchi  *   get the orderable OPN for this. The brand string doesn't feel appropriate
78dd23d762SRobert Mustacchi  *   for this use case.
79dd23d762SRobert Mustacchi  * o The FRU is always set to the top-level chip.
80dd23d762SRobert Mustacchi  * o We do not set the ASRU given that it will vary from device to device.
81dd23d762SRobert Mustacchi  */
82dd23d762SRobert Mustacchi static tnode_t *
topo_zen_create_tn(topo_mod_t * mod,zen_topo_enum_sock_t * sock,tnode_t * pnode,topo_instance_t inst,const char * name)83dd23d762SRobert Mustacchi topo_zen_create_tn(topo_mod_t *mod, zen_topo_enum_sock_t *sock, tnode_t *pnode,
84dd23d762SRobert Mustacchi     topo_instance_t inst, const char *name)
85dd23d762SRobert Mustacchi {
86dd23d762SRobert Mustacchi 	int ret, err;
87dd23d762SRobert Mustacchi 	tnode_t *tn = NULL;
88dd23d762SRobert Mustacchi 	nvlist_t *fmri = NULL, *auth = NULL;
89dd23d762SRobert Mustacchi 
90dd23d762SRobert Mustacchi 	auth = topo_mod_auth(mod, pnode);
91dd23d762SRobert Mustacchi 	if (auth == NULL) {
92dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to get auth for %s[%" PRIu64 "]: "
93dd23d762SRobert Mustacchi 		    "%s", name, inst, topo_mod_errmsg(mod));
94dd23d762SRobert Mustacchi 		return (NULL);
95dd23d762SRobert Mustacchi 	}
96dd23d762SRobert Mustacchi 
97dd23d762SRobert Mustacchi 	fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, name, inst,
98dd23d762SRobert Mustacchi 	    NULL, auth, NULL, sock->ztes_cpu_rev, sock->ztes_cpu_serial);
99dd23d762SRobert Mustacchi 	if (fmri == NULL) {
100dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to create FMRI for %s[%" PRIu64
101dd23d762SRobert Mustacchi 		    "]: %s", name, inst, topo_mod_errmsg(mod));
102dd23d762SRobert Mustacchi 		nvlist_free(auth);
103dd23d762SRobert Mustacchi 		return (NULL);
104dd23d762SRobert Mustacchi 	}
105dd23d762SRobert Mustacchi 
106dd23d762SRobert Mustacchi 	tn = topo_node_bind(mod, pnode, name, inst, fmri);
107dd23d762SRobert Mustacchi 	nvlist_free(auth);
108dd23d762SRobert Mustacchi 	if (tn == NULL) {
109dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to bind node %s[%" PRIu64 "]: %s",
110dd23d762SRobert Mustacchi 		    name, inst, topo_mod_errmsg(mod));
111dd23d762SRobert Mustacchi 		nvlist_free(fmri);
112dd23d762SRobert Mustacchi 		return (NULL);
113dd23d762SRobert Mustacchi 	}
114dd23d762SRobert Mustacchi 
115dd23d762SRobert Mustacchi 	if (sock->ztes_tn == NULL) {
116dd23d762SRobert Mustacchi 		ret = topo_node_fru_set(tn, fmri, 0, &err);
117dd23d762SRobert Mustacchi 	} else {
118dd23d762SRobert Mustacchi 		ret = topo_node_fru_set(tn, NULL, 0, &err);
119dd23d762SRobert Mustacchi 	}
120dd23d762SRobert Mustacchi 	nvlist_free(fmri);
121dd23d762SRobert Mustacchi 
122dd23d762SRobert Mustacchi 	if (ret != 0) {
123dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to set FRU for %s[%" PRIu64 "]: "
124dd23d762SRobert Mustacchi 		    "%s", name, inst, topo_strerror(err));
125dd23d762SRobert Mustacchi 		(void) topo_mod_seterrno(mod, err);
126dd23d762SRobert Mustacchi 		topo_node_unbind(tn);
127dd23d762SRobert Mustacchi 		return (NULL);
128dd23d762SRobert Mustacchi 	}
129dd23d762SRobert Mustacchi 
130dd23d762SRobert Mustacchi 	return (tn);
131dd23d762SRobert Mustacchi }
132dd23d762SRobert Mustacchi 
133dd23d762SRobert Mustacchi static tnode_t *
topo_zen_build_cache(topo_mod_t * mod,zen_topo_enum_sock_t * sock,tnode_t * pnode,topo_instance_t inst,nvlist_t * nvl)134dd23d762SRobert Mustacchi topo_zen_build_cache(topo_mod_t *mod, zen_topo_enum_sock_t *sock,
135dd23d762SRobert Mustacchi     tnode_t *pnode, topo_instance_t inst, nvlist_t *nvl)
136dd23d762SRobert Mustacchi {
137dd23d762SRobert Mustacchi 	int err;
138dd23d762SRobert Mustacchi 	uint32_t level, type, ways, line;
139dd23d762SRobert Mustacchi 	uint64_t sets, size, id;
140dd23d762SRobert Mustacchi 	const char *types[2];
141dd23d762SRobert Mustacchi 	const char *flags[2];
142dd23d762SRobert Mustacchi 	uint_t ntypes = 0, nflags = 0;
143dd23d762SRobert Mustacchi 
144dd23d762SRobert Mustacchi 	tnode_t *tn = topo_zen_create_tn(mod, sock, pnode, inst, CACHE);
145dd23d762SRobert Mustacchi 	if (tn == NULL) {
146dd23d762SRobert Mustacchi 		return (NULL);
147dd23d762SRobert Mustacchi 	}
148dd23d762SRobert Mustacchi 
149dd23d762SRobert Mustacchi 	if (nvlist_lookup_pairs(nvl, 0,
150dd23d762SRobert Mustacchi 	    FM_CACHE_INFO_LEVEL, DATA_TYPE_UINT32, &level,
151dd23d762SRobert Mustacchi 	    FM_CACHE_INFO_TYPE, DATA_TYPE_UINT32, &type,
152dd23d762SRobert Mustacchi 	    FM_CACHE_INFO_NWAYS, DATA_TYPE_UINT32, &ways,
153dd23d762SRobert Mustacchi 	    FM_CACHE_INFO_LINE_SIZE, DATA_TYPE_UINT32, &line,
154dd23d762SRobert Mustacchi 	    FM_CACHE_INFO_NSETS, DATA_TYPE_UINT64, &sets,
155dd23d762SRobert Mustacchi 	    FM_CACHE_INFO_TOTAL_SIZE, DATA_TYPE_UINT64, &size,
156dd23d762SRobert Mustacchi 	    FM_CACHE_INFO_ID, DATA_TYPE_UINT64, &id, NULL) != 0) {
157dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "internal cache nvlist missing expected "
158dd23d762SRobert Mustacchi 		    "keys");
159dd23d762SRobert Mustacchi 		goto err;
160dd23d762SRobert Mustacchi 	}
161dd23d762SRobert Mustacchi 
162dd23d762SRobert Mustacchi 	if ((type & FM_CACHE_INFO_T_DATA) != 0) {
163dd23d762SRobert Mustacchi 		types[ntypes] = TOPO_PGROUP_CACHE_TYPES_DATA;
164dd23d762SRobert Mustacchi 		ntypes++;
165dd23d762SRobert Mustacchi 	}
166dd23d762SRobert Mustacchi 
167dd23d762SRobert Mustacchi 	if ((type & FM_CACHE_INFO_T_INSTR) != 0) {
168dd23d762SRobert Mustacchi 		types[ntypes] = TOPO_PGROUP_CACHE_TYPES_INSTR;
169dd23d762SRobert Mustacchi 		ntypes++;
170dd23d762SRobert Mustacchi 	}
171dd23d762SRobert Mustacchi 
172dd23d762SRobert Mustacchi 	if ((type & FM_CACHE_INFO_T_UNIFIED) != 0) {
173dd23d762SRobert Mustacchi 		flags[nflags] = TOPO_PGROUP_CACHE_FLAGS_UNIFIED;
174dd23d762SRobert Mustacchi 		nflags++;
175dd23d762SRobert Mustacchi 	}
176dd23d762SRobert Mustacchi 
177dd23d762SRobert Mustacchi 	if (nvlist_lookup_boolean(nvl, FM_CACHE_INFO_FULLY_ASSOC) == 0) {
178dd23d762SRobert Mustacchi 		flags[nflags] = TOPO_PGROUP_CACHE_FLAGS_FA;
179dd23d762SRobert Mustacchi 		nflags++;
180dd23d762SRobert Mustacchi 	}
181dd23d762SRobert Mustacchi 
182dd23d762SRobert Mustacchi 	assert(ntypes > 0);
183dd23d762SRobert Mustacchi 	if (topo_create_props(mod, tn, TOPO_PROP_IMMUTABLE,
184dd23d762SRobert Mustacchi 	    &topo_zen_cache_pgroup,
185dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_LEVEL, TOPO_TYPE_UINT32, level,
186dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_WAYS, TOPO_TYPE_UINT32, ways,
187dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_SETS, TOPO_TYPE_UINT64, sets,
188dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_LINE_SIZE, TOPO_TYPE_UINT32, line,
189dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_SYSTEM_ID, TOPO_TYPE_UINT64, id,
190dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_SIZE, TOPO_TYPE_UINT64, size,
191dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_TYPES, TOPO_TYPE_STRING_ARRAY, types, ntypes,
192dd23d762SRobert Mustacchi 	    NULL) != 0) {
193dd23d762SRobert Mustacchi 		goto err;
194dd23d762SRobert Mustacchi 	}
195dd23d762SRobert Mustacchi 
196dd23d762SRobert Mustacchi 	if (nflags > 0 && topo_prop_set_string_array(tn, TOPO_PGROUP_CACHE,
197dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CACHE_FLAGS, TOPO_PROP_IMMUTABLE, flags, nflags,
198dd23d762SRobert Mustacchi 	    &err) != 0) {
199dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to create %s property: %s",
200dd23d762SRobert Mustacchi 		    TOPO_PGROUP_CACHE_FLAGS, topo_strerror(err));
201dd23d762SRobert Mustacchi 		(void) topo_mod_seterrno(mod, err);
202dd23d762SRobert Mustacchi 		goto err;
203dd23d762SRobert Mustacchi 	}
204dd23d762SRobert Mustacchi 
205dd23d762SRobert Mustacchi 	return (tn);
206dd23d762SRobert Mustacchi 
207dd23d762SRobert Mustacchi err:
208dd23d762SRobert Mustacchi 	topo_node_unbind(tn);
209dd23d762SRobert Mustacchi 	return (NULL);
210dd23d762SRobert Mustacchi 
211dd23d762SRobert Mustacchi }
212dd23d762SRobert Mustacchi 
213dd23d762SRobert Mustacchi /*
214dd23d762SRobert Mustacchi  * Build up an FMRI for the CPU scheme for this thread and set that as our ASRU
215dd23d762SRobert Mustacchi  * for the thread.
216dd23d762SRobert Mustacchi  */
217dd23d762SRobert Mustacchi static int
topo_zen_build_strand_asru(topo_mod_t * mod,zen_topo_enum_sock_t * sock,tnode_t * tn,uint32_t cpuid)218dd23d762SRobert Mustacchi topo_zen_build_strand_asru(topo_mod_t *mod, zen_topo_enum_sock_t *sock,
219dd23d762SRobert Mustacchi     tnode_t *tn, uint32_t cpuid)
220dd23d762SRobert Mustacchi {
221dd23d762SRobert Mustacchi 	int err, ret;
222dd23d762SRobert Mustacchi 	nvlist_t *fmri;
223dd23d762SRobert Mustacchi 
224dd23d762SRobert Mustacchi 	if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0) {
225dd23d762SRobert Mustacchi 		return (topo_mod_seterrno(mod, EMOD_NOMEM));
226dd23d762SRobert Mustacchi 	}
227dd23d762SRobert Mustacchi 
228dd23d762SRobert Mustacchi 	if (nvlist_add_uint8(fmri, FM_VERSION, FM_CPU_SCHEME_VERSION) != 0 ||
229dd23d762SRobert Mustacchi 	    nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_CPU) != 0 ||
230dd23d762SRobert Mustacchi 	    nvlist_add_uint32(fmri, FM_FMRI_CPU_ID, cpuid) != 0 ||
231*019df03dSRobert Mustacchi 	    (sock->ztes_cpu_serial != NULL && nvlist_add_string(fmri,
232*019df03dSRobert Mustacchi 	    FM_FMRI_CPU_SERIAL_ID, sock->ztes_cpu_serial) != 0)) {
233dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to construct CPU FMRI\n");
234dd23d762SRobert Mustacchi 		nvlist_free(fmri);
235dd23d762SRobert Mustacchi 		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
236dd23d762SRobert Mustacchi 	}
237dd23d762SRobert Mustacchi 
238dd23d762SRobert Mustacchi 	ret = topo_node_asru_set(tn, fmri, 0, &err);
239dd23d762SRobert Mustacchi 	nvlist_free(fmri);
240dd23d762SRobert Mustacchi 	if (ret != 0) {
241dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to set ASRU for thread: %s\n",
242dd23d762SRobert Mustacchi 		    topo_strerror(err));
243dd23d762SRobert Mustacchi 		return (topo_mod_seterrno(mod, err));
244dd23d762SRobert Mustacchi 	}
245dd23d762SRobert Mustacchi 
246dd23d762SRobert Mustacchi 	return (0);
247dd23d762SRobert Mustacchi }
248dd23d762SRobert Mustacchi 
249dd23d762SRobert Mustacchi static int
topo_zen_build_strand(topo_mod_t * mod,zen_topo_enum_sock_t * sock,const amdzen_topo_core_t * core,zen_topo_enum_core_t * zt_core,uint32_t tid)250dd23d762SRobert Mustacchi topo_zen_build_strand(topo_mod_t *mod, zen_topo_enum_sock_t *sock,
251dd23d762SRobert Mustacchi     const amdzen_topo_core_t *core, zen_topo_enum_core_t *zt_core, uint32_t tid)
252dd23d762SRobert Mustacchi {
253dd23d762SRobert Mustacchi 	uint32_t cpuid;
254dd23d762SRobert Mustacchi 	tnode_t *tn;
255dd23d762SRobert Mustacchi 
256dd23d762SRobert Mustacchi 	tn = topo_zen_create_tn(mod, sock, zt_core->ztcore_tn, tid, STRAND);
257dd23d762SRobert Mustacchi 	if (tn == NULL) {
258dd23d762SRobert Mustacchi 		return (-1);
259dd23d762SRobert Mustacchi 	}
260dd23d762SRobert Mustacchi 
261dd23d762SRobert Mustacchi 	/*
262dd23d762SRobert Mustacchi 	 * Strands (hardware threads) have an ASRU that relates to their logical
263dd23d762SRobert Mustacchi 	 * CPU. Set that up now. We currently only opt to set it on the strand
264dd23d762SRobert Mustacchi 	 * because if we want to offline the core, it seems like that needs
265dd23d762SRobert Mustacchi 	 * better semantics and perhaps wants a better way to indicate that in
266dd23d762SRobert Mustacchi 	 * the scheme.
267dd23d762SRobert Mustacchi 	 */
268dd23d762SRobert Mustacchi 	if (nvlist_lookup_pairs(zt_core->ztcore_nvls[tid], 0,
269dd23d762SRobert Mustacchi 	    FM_PHYSCPU_INFO_CPU_ID, DATA_TYPE_INT32,
270dd23d762SRobert Mustacchi 	    &cpuid, NULL) != 0) {
271dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "internal thread %u nvlist "
272dd23d762SRobert Mustacchi 		    "missing expected keys", tid);
273dd23d762SRobert Mustacchi 		topo_node_unbind(tn);
274dd23d762SRobert Mustacchi 		return (topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM));
275dd23d762SRobert Mustacchi 	}
276dd23d762SRobert Mustacchi 
277dd23d762SRobert Mustacchi 	if (topo_zen_build_strand_asru(mod, sock, tn, cpuid) != 0) {
278dd23d762SRobert Mustacchi 		topo_node_unbind(tn);
279dd23d762SRobert Mustacchi 		return (-1);
280dd23d762SRobert Mustacchi 	}
281dd23d762SRobert Mustacchi 
282dd23d762SRobert Mustacchi 	if (topo_create_props(mod, tn, TOPO_PROP_IMMUTABLE,
283dd23d762SRobert Mustacchi 	    &topo_zen_strand_pgroup,
284dd23d762SRobert Mustacchi 	    TOPO_PGROUP_STRAND_CPUID, TOPO_TYPE_UINT32, cpuid,
285dd23d762SRobert Mustacchi 	    TOPO_PGROUP_STRAND_APICID, TOPO_TYPE_UINT32,
286dd23d762SRobert Mustacchi 	    core->atcore_apicids[tid], NULL) != 0) {
287dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to set strand properties\n");
288dd23d762SRobert Mustacchi 		topo_node_unbind(tn);
289dd23d762SRobert Mustacchi 		return (-1);
290dd23d762SRobert Mustacchi 	}
291dd23d762SRobert Mustacchi 
292dd23d762SRobert Mustacchi 	zt_core->ztcore_thr_tn[tid] = tn;
293dd23d762SRobert Mustacchi 	return (0);
294dd23d762SRobert Mustacchi }
295dd23d762SRobert Mustacchi 
296dd23d762SRobert Mustacchi static int
topo_zen_build_core(topo_mod_t * mod,zen_topo_enum_sock_t * sock,tnode_t * ccx_tn,const amdzen_topo_core_t * core,zen_topo_enum_core_t * zt_core)297dd23d762SRobert Mustacchi topo_zen_build_core(topo_mod_t *mod, zen_topo_enum_sock_t *sock,
298dd23d762SRobert Mustacchi     tnode_t *ccx_tn, const amdzen_topo_core_t *core,
299dd23d762SRobert Mustacchi     zen_topo_enum_core_t *zt_core)
300dd23d762SRobert Mustacchi {
301dd23d762SRobert Mustacchi 	zt_core->ztcore_tn = topo_zen_create_tn(mod, sock, ccx_tn,
302dd23d762SRobert Mustacchi 	    core->atcore_phys_no, CORE);
303dd23d762SRobert Mustacchi 	if (zt_core->ztcore_tn == NULL) {
304dd23d762SRobert Mustacchi 		return (-1);
305dd23d762SRobert Mustacchi 	}
306dd23d762SRobert Mustacchi 
307dd23d762SRobert Mustacchi 	if (topo_create_props(mod, zt_core->ztcore_tn, TOPO_PROP_IMMUTABLE,
308dd23d762SRobert Mustacchi 	    &topo_zen_core_pgroup,
309dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CORE_LOGID, TOPO_TYPE_UINT32, core->atcore_log_no,
310dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CORE_PHYSID, TOPO_TYPE_UINT32, core->atcore_phys_no,
311dd23d762SRobert Mustacchi 	    NULL) != 0) {
312dd23d762SRobert Mustacchi 		return (-1);
313dd23d762SRobert Mustacchi 	}
314dd23d762SRobert Mustacchi 
315dd23d762SRobert Mustacchi 	if (topo_node_range_create(mod, zt_core->ztcore_tn, CACHE, 0, 2) != 0) {
316dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to create cache range: %s\n",
317dd23d762SRobert Mustacchi 		    topo_mod_errmsg(mod));
318dd23d762SRobert Mustacchi 		return (-1);
319dd23d762SRobert Mustacchi 	}
320dd23d762SRobert Mustacchi 
321dd23d762SRobert Mustacchi 	if (zt_core->ztcore_l2 != NULL) {
322dd23d762SRobert Mustacchi 		zt_core->ztcore_l2_tn = topo_zen_build_cache(mod, sock,
323dd23d762SRobert Mustacchi 		    zt_core->ztcore_tn, 2, zt_core->ztcore_l2);
324dd23d762SRobert Mustacchi 		if (zt_core->ztcore_l2_tn == NULL) {
325dd23d762SRobert Mustacchi 			return (-1);
326dd23d762SRobert Mustacchi 		}
327dd23d762SRobert Mustacchi 	}
328dd23d762SRobert Mustacchi 
329dd23d762SRobert Mustacchi 	if (zt_core->ztcore_l1i != NULL) {
330dd23d762SRobert Mustacchi 		zt_core->ztcore_l1i_tn = topo_zen_build_cache(mod, sock,
331dd23d762SRobert Mustacchi 		    zt_core->ztcore_tn, 1, zt_core->ztcore_l1i);
332dd23d762SRobert Mustacchi 		if (zt_core->ztcore_l1i_tn == NULL) {
333dd23d762SRobert Mustacchi 			return (-1);
334dd23d762SRobert Mustacchi 		}
335dd23d762SRobert Mustacchi 	}
336dd23d762SRobert Mustacchi 
337dd23d762SRobert Mustacchi 	if (zt_core->ztcore_l1d != NULL) {
338dd23d762SRobert Mustacchi 		zt_core->ztcore_l1d_tn = topo_zen_build_cache(mod, sock,
339dd23d762SRobert Mustacchi 		    zt_core->ztcore_tn, 0, zt_core->ztcore_l1d);
340dd23d762SRobert Mustacchi 		if (zt_core->ztcore_l1d_tn == NULL) {
341dd23d762SRobert Mustacchi 			return (-1);
342dd23d762SRobert Mustacchi 		}
343dd23d762SRobert Mustacchi 	}
344dd23d762SRobert Mustacchi 
345dd23d762SRobert Mustacchi 	if (topo_node_range_create(mod, zt_core->ztcore_tn, STRAND, 0,
346dd23d762SRobert Mustacchi 	    core->atcore_nthreads - 1) != 0) {
347dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to create strand range: %s\n",
348dd23d762SRobert Mustacchi 		    topo_mod_errmsg(mod));
349dd23d762SRobert Mustacchi 		return (-1);
350dd23d762SRobert Mustacchi 	}
351dd23d762SRobert Mustacchi 
352dd23d762SRobert Mustacchi 	for (uint32_t tid = 0; tid < core->atcore_nthreads; tid++) {
353dd23d762SRobert Mustacchi 		int ret;
354dd23d762SRobert Mustacchi 
355dd23d762SRobert Mustacchi 		if (core->atcore_thr_en[tid] == 0) {
356dd23d762SRobert Mustacchi 			continue;
357dd23d762SRobert Mustacchi 		}
358dd23d762SRobert Mustacchi 
359dd23d762SRobert Mustacchi 		if ((ret = topo_zen_build_strand(mod, sock, core, zt_core,
360dd23d762SRobert Mustacchi 		    tid)) != 0) {
361dd23d762SRobert Mustacchi 			return (ret);
362dd23d762SRobert Mustacchi 		}
363dd23d762SRobert Mustacchi 	}
364dd23d762SRobert Mustacchi 
365dd23d762SRobert Mustacchi 	return (0);
366dd23d762SRobert Mustacchi }
367dd23d762SRobert Mustacchi 
368dd23d762SRobert Mustacchi static int
topo_zen_build_ccx(topo_mod_t * mod,zen_topo_enum_sock_t * sock,tnode_t * ccd_tn,const amdzen_topo_ccx_t * ccx,zen_topo_enum_ccx_t * zt_ccx)369dd23d762SRobert Mustacchi topo_zen_build_ccx(topo_mod_t *mod, zen_topo_enum_sock_t *sock, tnode_t *ccd_tn,
370dd23d762SRobert Mustacchi     const amdzen_topo_ccx_t *ccx, zen_topo_enum_ccx_t *zt_ccx)
371dd23d762SRobert Mustacchi {
372dd23d762SRobert Mustacchi 	zt_ccx->ztccx_tn = topo_zen_create_tn(mod, sock, ccd_tn,
373dd23d762SRobert Mustacchi 	    ccx->atccx_phys_no, CCX);
374dd23d762SRobert Mustacchi 	if (zt_ccx->ztccx_tn == NULL) {
375dd23d762SRobert Mustacchi 		return (-1);
376dd23d762SRobert Mustacchi 	}
377dd23d762SRobert Mustacchi 
378dd23d762SRobert Mustacchi 	if (topo_create_props(mod, zt_ccx->ztccx_tn, TOPO_PROP_IMMUTABLE,
379dd23d762SRobert Mustacchi 	    &topo_zen_ccx_pgroup,
380dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CCX_LOGID, TOPO_TYPE_UINT32, ccx->atccx_log_no,
381dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CCX_PHYSID, TOPO_TYPE_UINT32, ccx->atccx_phys_no,
382dd23d762SRobert Mustacchi 	    NULL) != 0) {
383dd23d762SRobert Mustacchi 		topo_node_unbind(zt_ccx->ztccx_tn);
384dd23d762SRobert Mustacchi 		zt_ccx->ztccx_tn = NULL;
385dd23d762SRobert Mustacchi 		return (-1);
386dd23d762SRobert Mustacchi 	}
387dd23d762SRobert Mustacchi 
388dd23d762SRobert Mustacchi 	if (topo_node_range_create(mod, zt_ccx->ztccx_tn, CACHE, 0, 0) != 0) {
389dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to create cache range: %s\n",
390dd23d762SRobert Mustacchi 		    topo_mod_errmsg(mod));
391dd23d762SRobert Mustacchi 		topo_node_unbind(zt_ccx->ztccx_tn);
392dd23d762SRobert Mustacchi 		zt_ccx->ztccx_tn = NULL;
393dd23d762SRobert Mustacchi 		return (-1);
394dd23d762SRobert Mustacchi 	}
395dd23d762SRobert Mustacchi 
396dd23d762SRobert Mustacchi 	if (zt_ccx->ztccx_l3 != NULL) {
397dd23d762SRobert Mustacchi 		zt_ccx->ztccx_l3_tn = topo_zen_build_cache(mod, sock,
398dd23d762SRobert Mustacchi 		    zt_ccx->ztccx_tn, 0, zt_ccx->ztccx_l3);
399dd23d762SRobert Mustacchi 		if (zt_ccx->ztccx_l3_tn == NULL) {
400dd23d762SRobert Mustacchi 			return (-1);
401dd23d762SRobert Mustacchi 		}
402dd23d762SRobert Mustacchi 	}
403dd23d762SRobert Mustacchi 
404dd23d762SRobert Mustacchi 	if (topo_node_range_create(mod, zt_ccx->ztccx_tn, CORE, 0,
405dd23d762SRobert Mustacchi 	    ccx->atccx_nphys_cores - 1) != 0) {
406dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to create cores range: %s\n",
407dd23d762SRobert Mustacchi 		    topo_mod_errmsg(mod));
408dd23d762SRobert Mustacchi 		return (-1);
409dd23d762SRobert Mustacchi 	}
410dd23d762SRobert Mustacchi 
411dd23d762SRobert Mustacchi 	for (uint32_t coreno = 0; coreno < ccx->atccx_nphys_cores; coreno++) {
412dd23d762SRobert Mustacchi 		int ret;
413dd23d762SRobert Mustacchi 
414dd23d762SRobert Mustacchi 		if (ccx->atccx_core_en[coreno] == 0) {
415dd23d762SRobert Mustacchi 			topo_mod_dprintf(mod, "skipping core %u\n", coreno);
416dd23d762SRobert Mustacchi 			continue;
417dd23d762SRobert Mustacchi 		}
418dd23d762SRobert Mustacchi 
419dd23d762SRobert Mustacchi 		if ((ret = topo_zen_build_core(mod, sock, zt_ccx->ztccx_tn,
420dd23d762SRobert Mustacchi 		    &ccx->atccx_cores[coreno], &zt_ccx->ztccx_core[coreno])) !=
421dd23d762SRobert Mustacchi 		    0) {
422dd23d762SRobert Mustacchi 			return (ret);
423dd23d762SRobert Mustacchi 		}
424dd23d762SRobert Mustacchi 	}
425dd23d762SRobert Mustacchi 
426dd23d762SRobert Mustacchi 	return (0);
427dd23d762SRobert Mustacchi }
428dd23d762SRobert Mustacchi 
429dd23d762SRobert Mustacchi static int
topo_zen_build_ccds(topo_mod_t * mod,zen_topo_enum_sock_t * sock)430dd23d762SRobert Mustacchi topo_zen_build_ccds(topo_mod_t *mod, zen_topo_enum_sock_t *sock)
431dd23d762SRobert Mustacchi {
432dd23d762SRobert Mustacchi 	tnode_t *chip = sock->ztes_tn;
433dd23d762SRobert Mustacchi 
434dd23d762SRobert Mustacchi 	if (topo_node_range_create(mod, chip, CCD, 0, sock->ztes_nccd - 1) !=
435dd23d762SRobert Mustacchi 	    0) {
436dd23d762SRobert Mustacchi 		topo_mod_dprintf(mod, "failed to create CCD range: %s\n",
437dd23d762SRobert Mustacchi 		    topo_mod_errmsg(mod));
438dd23d762SRobert Mustacchi 		return (-1);
439dd23d762SRobert Mustacchi 	}
440dd23d762SRobert Mustacchi 
441dd23d762SRobert Mustacchi 	for (uint32_t ccdno = 0; ccdno < sock->ztes_nccd; ccdno++) {
442dd23d762SRobert Mustacchi 		const amdzen_topo_ccd_t *ccd = &sock->ztes_ccd[ccdno];
443dd23d762SRobert Mustacchi 		zen_topo_enum_ccd_t *zt_ccd = &sock->ztes_tn_ccd[ccdno];
444dd23d762SRobert Mustacchi 
445dd23d762SRobert Mustacchi 		/*
446dd23d762SRobert Mustacchi 		 * Make sure we skip any CCDs that don't actually exist.
447dd23d762SRobert Mustacchi 		 */
448dd23d762SRobert Mustacchi 		if (ccd->atccd_err != AMDZEN_TOPO_CCD_E_OK) {
449dd23d762SRobert Mustacchi 			continue;
450dd23d762SRobert Mustacchi 		}
451dd23d762SRobert Mustacchi 
452dd23d762SRobert Mustacchi 		zt_ccd->ztccd_tn = topo_zen_create_tn(mod, sock, chip, ccdno,
453dd23d762SRobert Mustacchi 		    CCD);
454dd23d762SRobert Mustacchi 		if (zt_ccd->ztccd_tn == NULL) {
455dd23d762SRobert Mustacchi 			return (-1);
456dd23d762SRobert Mustacchi 		}
457dd23d762SRobert Mustacchi 
458dd23d762SRobert Mustacchi 		if (topo_create_props(mod, zt_ccd->ztccd_tn,
459dd23d762SRobert Mustacchi 		    TOPO_PROP_IMMUTABLE, &topo_zen_ccd_pgroup,
460dd23d762SRobert Mustacchi 		    TOPO_PGROUP_CCD_LOGID, TOPO_TYPE_UINT32, ccd->atccd_log_no,
461dd23d762SRobert Mustacchi 		    TOPO_PGROUP_CCD_PHYSID, TOPO_TYPE_UINT32,
462dd23d762SRobert Mustacchi 		    ccd->atccd_phys_no, NULL) != 0) {
463dd23d762SRobert Mustacchi 			topo_node_unbind(zt_ccd->ztccd_tn);
464dd23d762SRobert Mustacchi 			zt_ccd->ztccd_tn = NULL;
465dd23d762SRobert Mustacchi 			return (-1);
466dd23d762SRobert Mustacchi 		}
467dd23d762SRobert Mustacchi 
468dd23d762SRobert Mustacchi 		/*
469dd23d762SRobert Mustacchi 		 * At this point we should go create any additional sensors
470dd23d762SRobert Mustacchi 		 * (such as the per-CCD Tctl) and probably set some methods,
471dd23d762SRobert Mustacchi 		 * etc.
472dd23d762SRobert Mustacchi 		 */
473dd23d762SRobert Mustacchi 
474dd23d762SRobert Mustacchi 		if (topo_node_range_create(mod, zt_ccd->ztccd_tn, CCX, 0,
475dd23d762SRobert Mustacchi 		    ccd->atccd_nphys_ccx) != 0) {
476dd23d762SRobert Mustacchi 			topo_mod_dprintf(mod, "failed to create CCD range: "
477dd23d762SRobert Mustacchi 			    "%s\n", topo_mod_errmsg(mod));
478dd23d762SRobert Mustacchi 			return (-1);
479dd23d762SRobert Mustacchi 		}
480dd23d762SRobert Mustacchi 
481dd23d762SRobert Mustacchi 		for (uint32_t ccxno = 0; ccxno < ccd->atccd_nphys_ccx;
482dd23d762SRobert Mustacchi 		    ccxno++) {
483dd23d762SRobert Mustacchi 			int ret;
484dd23d762SRobert Mustacchi 
485dd23d762SRobert Mustacchi 			if (ccd->atccd_ccx_en[ccxno] == 0) {
486dd23d762SRobert Mustacchi 				continue;
487dd23d762SRobert Mustacchi 			}
488dd23d762SRobert Mustacchi 
489dd23d762SRobert Mustacchi 			if ((ret = topo_zen_build_ccx(mod, sock,
490dd23d762SRobert Mustacchi 			    zt_ccd->ztccd_tn, &ccd->atccd_ccx[ccxno],
491dd23d762SRobert Mustacchi 			    &zt_ccd->ztccd_ccx[ccxno])) != 0) {
492dd23d762SRobert Mustacchi 				return (ret);
493dd23d762SRobert Mustacchi 			}
494dd23d762SRobert Mustacchi 		}
495dd23d762SRobert Mustacchi 	}
496dd23d762SRobert Mustacchi 
497dd23d762SRobert Mustacchi 	return (0);
498dd23d762SRobert Mustacchi }
499dd23d762SRobert Mustacchi 
500dd23d762SRobert Mustacchi int
topo_zen_build_chip(topo_mod_t * mod,tnode_t * pnode,topo_instance_t inst,zen_topo_enum_sock_t * sock)501dd23d762SRobert Mustacchi topo_zen_build_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst,
502dd23d762SRobert Mustacchi     zen_topo_enum_sock_t *sock)
503dd23d762SRobert Mustacchi {
504dd23d762SRobert Mustacchi 	int ret;
505dd23d762SRobert Mustacchi 	tnode_t *chip;
506dd23d762SRobert Mustacchi 
507dd23d762SRobert Mustacchi 	chip = topo_zen_create_tn(mod, sock, pnode, inst, CHIP);
508dd23d762SRobert Mustacchi 	if (chip == NULL) {
509dd23d762SRobert Mustacchi 		return (-1);
510dd23d762SRobert Mustacchi 	}
511dd23d762SRobert Mustacchi 
512dd23d762SRobert Mustacchi 	if (topo_create_props(mod, chip, TOPO_PROP_IMMUTABLE,
513dd23d762SRobert Mustacchi 	    &topo_zen_chip_pgroup,
514dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CHIP_BRAND, TOPO_TYPE_STRING, sock->ztes_cpu_brand,
515dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CHIP_FAMILY, TOPO_TYPE_INT32, sock->ztes_cpu_fam,
516dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CHIP_MODEL, TOPO_TYPE_INT32, sock->ztes_cpu_model,
517dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CHIP_STEPPING, TOPO_TYPE_INT32, sock->ztes_cpu_step,
518dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CHIP_SOCKET, TOPO_TYPE_STRING, sock->ztes_cpu_sock,
519*019df03dSRobert Mustacchi 	    NULL) != 0) {
520*019df03dSRobert Mustacchi 		topo_node_unbind(chip);
521*019df03dSRobert Mustacchi 		return (-1);
522*019df03dSRobert Mustacchi 	}
523*019df03dSRobert Mustacchi 
524*019df03dSRobert Mustacchi 	if (sock->ztes_cpu_rev != NULL && topo_create_props(mod, chip,
525*019df03dSRobert Mustacchi 	    TOPO_PROP_IMMUTABLE, &topo_zen_chip_pgroup,
526dd23d762SRobert Mustacchi 	    TOPO_PGROUP_CHIP_REVISION, TOPO_TYPE_STRING, sock->ztes_cpu_rev,
527dd23d762SRobert Mustacchi 	    NULL) != 0) {
528dd23d762SRobert Mustacchi 		topo_node_unbind(chip);
529dd23d762SRobert Mustacchi 		return (-1);
530dd23d762SRobert Mustacchi 	}
531dd23d762SRobert Mustacchi 
532dd23d762SRobert Mustacchi 	sock->ztes_tn = chip;
533dd23d762SRobert Mustacchi 	ret = topo_zen_build_ccds(mod, sock);
534dd23d762SRobert Mustacchi 
535dd23d762SRobert Mustacchi 	/*
536dd23d762SRobert Mustacchi 	 * At this point we should flesh out the I/O die and all the UMCs, IOMS
537dd23d762SRobert Mustacchi 	 * instances, and related. we would put the general thermal sensor that
538dd23d762SRobert Mustacchi 	 * smntemp exposes as procnode.%u under the I/O die when we have it.
539dd23d762SRobert Mustacchi 	 */
540dd23d762SRobert Mustacchi 
541dd23d762SRobert Mustacchi 	return (ret);
542dd23d762SRobert Mustacchi }
543