chip.c (f2dbfd32) chip.c (d0caeb89)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2019, Joyent, Inc.
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2019, Joyent, Inc.
26 * Copyright 2020 Oxide Computer Company
26 */
27
28#include <unistd.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <stdarg.h>
33#include <string.h>
34#include <strings.h>
35#include <limits.h>
36#include <alloca.h>
37#include <kstat.h>
38#include <errno.h>
39#include <libnvpair.h>
40#include <sys/types.h>
41#include <sys/bitmap.h>
42#include <sys/processor.h>
43#include <sys/param.h>
44#include <sys/fm/protocol.h>
45#include <sys/systeminfo.h>
46#include <sys/mc.h>
47#include <sys/mc_amd.h>
48#include <sys/mc_intel.h>
49#include <sys/devfm.h>
50#include <fm/fmd_agent.h>
51#include <fm/topo_mod.h>
52
53#include "chip.h"
54
55#define MAX_DIMMNUM 7
56#define MAX_CSNUM 7
57
58/*
59 * Enumerates the processing chips, or sockets, (as distinct from cores) in a
60 * system. For each chip found, the necessary nodes (one or more cores, and
61 * possibly a memory controller) are constructed underneath.
62 */
63
64static int chip_enum(topo_mod_t *, tnode_t *, const char *,
65 topo_instance_t, topo_instance_t, void *, void *);
66
67static const topo_modops_t chip_ops =
68 { chip_enum, NULL};
69static const topo_modinfo_t chip_info =
70 { CHIP_NODE_NAME, FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops };
71
72static const topo_pgroup_info_t chip_pgroup =
73 { PGNAME(CHIP), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
74
75static const topo_pgroup_info_t core_pgroup =
76 { PGNAME(CORE), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
77
78static const topo_pgroup_info_t strand_pgroup =
79 { PGNAME(STRAND), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
80
81static const topo_method_t chip_methods[] = {
82 { SIMPLE_CHIP_LBL, "Property method", 0,
83 TOPO_STABILITY_INTERNAL, simple_chip_label},
84 { G4_CHIP_LBL, "Property method", 0,
85 TOPO_STABILITY_INTERNAL, g4_chip_label},
86 { A4FPLUS_CHIP_LBL, "Property method", 0,
87 TOPO_STABILITY_INTERNAL, a4fplus_chip_label},
88 { FSB2_CHIP_LBL, "Property method", 0,
89 TOPO_STABILITY_INTERNAL, fsb2_chip_label},
90 { TOPO_METH_REPLACED, TOPO_METH_REPLACED_DESC,
91 TOPO_METH_REPLACED_VERSION, TOPO_STABILITY_INTERNAL,
92 chip_fmri_replaced },
93 { NULL }
94};
95
96static const topo_method_t strands_retire_methods[] = {
97 { TOPO_METH_RETIRE, TOPO_METH_RETIRE_DESC,
98 TOPO_METH_RETIRE_VERSION, TOPO_STABILITY_INTERNAL,
99 retire_strands },
100 { TOPO_METH_UNRETIRE, TOPO_METH_UNRETIRE_DESC,
101 TOPO_METH_UNRETIRE_VERSION, TOPO_STABILITY_INTERNAL,
102 unretire_strands },
103 { TOPO_METH_SERVICE_STATE, TOPO_METH_SERVICE_STATE_DESC,
104 TOPO_METH_SERVICE_STATE_VERSION, TOPO_STABILITY_INTERNAL,
105 service_state_strands },
106 { TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC,
107 TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL,
108 unusable_strands },
109 { NULL }
110};
111
112int
113_topo_init(topo_mod_t *mod)
114{
115 if (getenv("TOPOCHIPDBG"))
116 topo_mod_setdebug(mod);
117 topo_mod_dprintf(mod, "initializing chip enumerator\n");
118
119 if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
120 whinge(mod, NULL, "failed to register hc: "
121 "%s\n", topo_mod_errmsg(mod));
122 return (-1); /* mod errno set */
123 }
124
125 return (0);
126}
127
128void
129_topo_fini(topo_mod_t *mod)
130{
131 topo_mod_unregister(mod);
132}
133
134boolean_t
135is_xpv(void)
136{
137 static int r = -1;
138 char platform[MAXNAMELEN];
139
140 if (r != -1)
141 return (r == 0);
142
143 (void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
144 r = strcmp(platform, "i86xpv");
145 return (r == 0);
146}
147
148static tnode_t *
149create_node(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, char *name,
150 topo_instance_t inst, nvlist_t *cpu, uint16_t smbios_id)
151{
152 nvlist_t *fmri;
153 tnode_t *cnode;
154
155 if (mkrsrc(mod, pnode, name, inst, auth, &fmri) != 0) {
156 whinge(mod, NULL, "create_node: mkrsrc failed\n");
157 return (NULL);
158 }
159
160 if (FM_AWARE_SMBIOS(mod)) {
161 id_t phys_cpu_smbid;
162 int perr = 0;
163 const char *serial = NULL;
164 const char *part = NULL;
165 const char *rev = NULL;
166
167 phys_cpu_smbid = smbios_id;
168 serial = chip_serial_smbios_get(mod, phys_cpu_smbid);
169 part = chip_part_smbios_get(mod, phys_cpu_smbid);
170 rev = chip_rev_smbios_get(mod, phys_cpu_smbid);
171
172 perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
173 serial);
174 perr += nvlist_add_string(fmri, FM_FMRI_HC_PART,
175 part);
176 perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION,
177 rev);
178
179 if (perr != 0)
180 whinge(mod, NULL,
181 "create_node: nvlist_add_string failed\n");
182
183 topo_mod_strfree(mod, (char *)serial);
184 topo_mod_strfree(mod, (char *)part);
185 topo_mod_strfree(mod, (char *)rev);
186 } else {
187 char *serial = NULL;
188
189 if (nvlist_lookup_string(cpu, FM_PHYSCPU_INFO_CHIP_IDENTSTR,
190 &serial) == 0) {
191 if (nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
192 serial) != 0) {
193 whinge(mod, NULL,
194 "create_node: nvlist_add_string failed\n");
195 }
196 }
197 }
198
199 cnode = topo_node_bind(mod, pnode, name, inst, fmri);
200
201 nvlist_free(fmri);
202 if (cnode == NULL) {
203 whinge(mod, NULL, "create_node: node bind failed"
204 " for %s %d\n", name, (int)inst);
205 }
206
207 return (cnode);
208}
209
210static int
211create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
212 nvlist_t *auth, uint16_t chip_smbiosid)
213{
214 tnode_t *strand;
215 int32_t strandid, cpuid;
216 int err, perr, nerr = 0;
217 nvlist_t *fmri;
218 char *serial = NULL;
219 char *part = NULL;
220 char *rev = NULL;
221
222 if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
223 &strandid)) != 0) {
224 whinge(mod, NULL, "create_strand: lookup strand_id failed: "
225 "%s\n", strerror(err));
226 return (-1);
227 }
228
229 if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid))
230 != NULL) {
231 whinge(mod, NULL, "create_strand: duplicate tuple found\n");
232 return (-1);
233 }
234
235 if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
236 strandid, cpu, chip_smbiosid)) == NULL)
237 return (-1);
238
239 /*
240 * Inherit FRU from core node, in native use cpu scheme ASRU,
241 * in xpv, use hc scheme ASRU.
242 */
243 (void) topo_node_fru_set(strand, NULL, 0, &perr);
244 /*
245 * From the inherited FRU, extract the Serial
246 * number(if SMBIOS donates) and set it in the ASRU
247 */
248 if (FM_AWARE_SMBIOS(mod)) {
249 char *val = NULL;
250
251 if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
252 TOPO_PROP_RESOURCE, &fmri, &err) != 0)
253 whinge(mod, NULL,
254 "create_strand: topo_prop_get_fmri failed\n");
255 if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0)
256 whinge(mod, NULL,
257 "create_strand: nvlist_lookup_string failed: \n");
258 else
259 serial = topo_mod_strdup(mod, val);
260 nvlist_free(fmri);
261 }
262 if (is_xpv()) {
263 if (topo_node_resource(strand, &fmri, &err) == -1) {
264 whinge(mod, &nerr, "create_strand: "
265 "topo_node_resource failed\n");
266 } else {
267 if (FM_AWARE_SMBIOS(mod))
268 (void) nvlist_add_string(fmri,
269 FM_FMRI_HC_SERIAL_ID, serial);
270 (void) topo_node_asru_set(strand, fmri, 0, &err);
271 nvlist_free(fmri);
272 }
273 } else {
274 if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
275 whinge(mod, &nerr, "create_strand: lookup cpuid "
276 "failed\n");
277 } else {
278 if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
279 != NULL) {
280 (void) topo_node_asru_set(strand, fmri,
281 0, &err);
282 nvlist_free(fmri);
283 } else {
284 whinge(mod, &nerr, "create_strand: "
285 "cpu_fmri_create() failed\n");
286 }
287 }
288 }
289
290 if (topo_method_register(mod, strand, strands_retire_methods) < 0)
291 whinge(mod, &nerr, "create_strand: "
292 "topo_method_register failed\n");
293
294 (void) topo_pgroup_create(strand, &strand_pgroup, &err);
295 nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
296 STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID,
297 NULL);
298
299 if (FM_AWARE_SMBIOS(mod)) {
300 (void) topo_node_label_set(strand, NULL, &perr);
301
302 if (topo_node_resource(strand, &fmri, &perr) != 0) {
303 whinge(mod, &nerr, "create_strand: "
304 "topo_node_resource failed\n");
305 perr = 0;
306 }
307
308 perr += nvlist_lookup_string(fmri,
309 FM_FMRI_HC_PART, &part);
310 perr += nvlist_lookup_string(fmri,
311 FM_FMRI_HC_REVISION, &rev);
312
313 if (perr != 0) {
314 whinge(mod, NULL,
315 "create_strand: nvlist_lookup_string failed\n");
316 perr = 0;
317 }
318
319 perr += topo_prop_set_string(strand, PGNAME(STRAND),
320 FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
321 perr += topo_prop_set_string(strand, PGNAME(STRAND),
322 FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
323 perr += topo_prop_set_string(strand, PGNAME(STRAND),
324 FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
325
326 if (perr != 0)
327 whinge(mod, NULL, "create_strand: topo_prop_set_string"
328 "failed\n");
329
330 nvlist_free(fmri);
331 topo_mod_strfree(mod, serial);
332 }
333
334 return (err == 0 && nerr == 0 ? 0 : -1);
335}
336
337static int
338create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
339 nvlist_t *auth, uint16_t chip_smbiosid)
340{
341 tnode_t *core;
342 int32_t coreid, cpuid;
343 int err, perr, nerr = 0;
344 nvlist_t *fmri;
345 char *serial = NULL;
346 char *part = NULL;
347 char *rev = NULL;
348
349 if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
350 != 0) {
351 whinge(mod, NULL, "create_core: lookup core_id failed: %s\n",
352 strerror(err));
353 return (-1);
354 }
355 if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
356 if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
357 coreid, cpu, chip_smbiosid)) == NULL)
358 return (-1);
359
360 /*
361 * Inherit FRU from the chip node, for native, we use hc
362 * scheme ASRU for the core node.
363 */
364 (void) topo_node_fru_set(core, NULL, 0, &perr);
365 /*
366 * From the inherited FRU, extract the Serial
367 * number if SMBIOS donates and set it in the ASRU
368 */
369 if (FM_AWARE_SMBIOS(mod)) {
370 char *val = NULL;
371
372 if (topo_node_resource(core, &fmri, &err) != 0)
373 whinge(mod, NULL,
374 "create_core: topo_prop_get_fmri failed\n");
375 if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID,
376 &val) != 0)
377 whinge(mod, NULL, "create_core:"
378 "nvlist_lookup_string failed\n");
379 else
380 serial = topo_mod_strdup(mod, val);
381 nvlist_free(fmri);
382 }
383 if (is_xpv()) {
384 if (topo_node_resource(core, &fmri, &err) == -1) {
385 whinge(mod, &nerr, "create_core: "
386 "topo_node_resource failed\n");
387 } else {
388 if (FM_AWARE_SMBIOS(mod))
389 (void) nvlist_add_string(fmri,
390 FM_FMRI_HC_SERIAL_ID, serial);
391 (void) topo_node_asru_set(core, fmri, 0, &err);
392 nvlist_free(fmri);
393 }
394 }
395 if (topo_method_register(mod, core, strands_retire_methods) < 0)
396 whinge(mod, &nerr, "create_core: "
397 "topo_method_register failed\n");
398
399 (void) topo_pgroup_create(core, &core_pgroup, &err);
400 nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL,
401 CORE_CHIP_ID, CORE_PROCNODE_ID, NULL);
402
403 if (topo_node_range_create(mod, core, STRAND_NODE_NAME,
404 0, 255) != 0)
405 return (-1);
406
407 /*
408 * Creating a temperature sensor may fail because the sensor
409 * doesn't exist or due to internal reasons. At the moment, we
410 * swallow any such errors that occur.
411 */
412 (void) chip_create_core_temp_sensor(mod, core);
413 }
414
415 if (!is_xpv()) {
416 /*
417 * In native mode, we're in favor of cpu scheme ASRU for
418 * printing reason. More work needs to be done to support
419 * multi-strand cpu: the ASRU will be a list of cpuid then.
420 */
421 if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
422 whinge(mod, &nerr, "create_core: lookup cpuid "
423 "failed\n");
424 } else {
425 if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
426 != NULL) {
427 (void) topo_node_asru_set(core, fmri, 0, &err);
428 nvlist_free(fmri);
429 } else {
430 whinge(mod, &nerr, "create_core: "
431 "cpu_fmri_create() failed\n");
432 }
433 }
434 }
435
436 if (FM_AWARE_SMBIOS(mod)) {
437 (void) topo_node_label_set(core, NULL, &perr);
438
439 if (topo_node_resource(core, &fmri, &perr) != 0) {
440 whinge(mod, &nerr, "create_core: "
441 "topo_node_resource failed\n");
442 perr = 0;
443 }
444
445 perr += nvlist_lookup_string(fmri,
446 FM_FMRI_HC_PART, &part);
447 perr += nvlist_lookup_string(fmri,
448 FM_FMRI_HC_REVISION, &rev);
449
450 if (perr != 0) {
451 whinge(mod, NULL,
452 "create_core: nvlist_lookup_string failed\n");
453 perr = 0;
454 }
455
456 perr += topo_prop_set_string(core, PGNAME(CORE),
457 FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
458 perr += topo_prop_set_string(core, PGNAME(CORE),
459 FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
460 perr += topo_prop_set_string(core, PGNAME(CORE),
461 FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
462
463 if (perr != 0)
464 whinge(mod, NULL, "create_core: topo_prop_set_string"
465 "failed\n");
466
467 nvlist_free(fmri);
468 topo_mod_strfree(mod, serial);
469 }
470
471 err = create_strand(mod, core, cpu, auth, chip_smbiosid);
472
473 return (err == 0 && nerr == 0 ? 0 : -1);
474}
475
476static int
477create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
478 topo_instance_t max, nvlist_t *cpu, nvlist_t *auth,
479 int mc_offchip, kstat_ctl_t *kc)
480{
481 tnode_t *chip;
482 nvlist_t *fmri = NULL;
483 int err, perr, nerr = 0;
484 int32_t chipid, procnodeid, procnodes_per_pkg;
27 */
28
29#include <unistd.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <string.h>
35#include <strings.h>
36#include <limits.h>
37#include <alloca.h>
38#include <kstat.h>
39#include <errno.h>
40#include <libnvpair.h>
41#include <sys/types.h>
42#include <sys/bitmap.h>
43#include <sys/processor.h>
44#include <sys/param.h>
45#include <sys/fm/protocol.h>
46#include <sys/systeminfo.h>
47#include <sys/mc.h>
48#include <sys/mc_amd.h>
49#include <sys/mc_intel.h>
50#include <sys/devfm.h>
51#include <fm/fmd_agent.h>
52#include <fm/topo_mod.h>
53
54#include "chip.h"
55
56#define MAX_DIMMNUM 7
57#define MAX_CSNUM 7
58
59/*
60 * Enumerates the processing chips, or sockets, (as distinct from cores) in a
61 * system. For each chip found, the necessary nodes (one or more cores, and
62 * possibly a memory controller) are constructed underneath.
63 */
64
65static int chip_enum(topo_mod_t *, tnode_t *, const char *,
66 topo_instance_t, topo_instance_t, void *, void *);
67
68static const topo_modops_t chip_ops =
69 { chip_enum, NULL};
70static const topo_modinfo_t chip_info =
71 { CHIP_NODE_NAME, FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops };
72
73static const topo_pgroup_info_t chip_pgroup =
74 { PGNAME(CHIP), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
75
76static const topo_pgroup_info_t core_pgroup =
77 { PGNAME(CORE), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
78
79static const topo_pgroup_info_t strand_pgroup =
80 { PGNAME(STRAND), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
81
82static const topo_method_t chip_methods[] = {
83 { SIMPLE_CHIP_LBL, "Property method", 0,
84 TOPO_STABILITY_INTERNAL, simple_chip_label},
85 { G4_CHIP_LBL, "Property method", 0,
86 TOPO_STABILITY_INTERNAL, g4_chip_label},
87 { A4FPLUS_CHIP_LBL, "Property method", 0,
88 TOPO_STABILITY_INTERNAL, a4fplus_chip_label},
89 { FSB2_CHIP_LBL, "Property method", 0,
90 TOPO_STABILITY_INTERNAL, fsb2_chip_label},
91 { TOPO_METH_REPLACED, TOPO_METH_REPLACED_DESC,
92 TOPO_METH_REPLACED_VERSION, TOPO_STABILITY_INTERNAL,
93 chip_fmri_replaced },
94 { NULL }
95};
96
97static const topo_method_t strands_retire_methods[] = {
98 { TOPO_METH_RETIRE, TOPO_METH_RETIRE_DESC,
99 TOPO_METH_RETIRE_VERSION, TOPO_STABILITY_INTERNAL,
100 retire_strands },
101 { TOPO_METH_UNRETIRE, TOPO_METH_UNRETIRE_DESC,
102 TOPO_METH_UNRETIRE_VERSION, TOPO_STABILITY_INTERNAL,
103 unretire_strands },
104 { TOPO_METH_SERVICE_STATE, TOPO_METH_SERVICE_STATE_DESC,
105 TOPO_METH_SERVICE_STATE_VERSION, TOPO_STABILITY_INTERNAL,
106 service_state_strands },
107 { TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC,
108 TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL,
109 unusable_strands },
110 { NULL }
111};
112
113int
114_topo_init(topo_mod_t *mod)
115{
116 if (getenv("TOPOCHIPDBG"))
117 topo_mod_setdebug(mod);
118 topo_mod_dprintf(mod, "initializing chip enumerator\n");
119
120 if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
121 whinge(mod, NULL, "failed to register hc: "
122 "%s\n", topo_mod_errmsg(mod));
123 return (-1); /* mod errno set */
124 }
125
126 return (0);
127}
128
129void
130_topo_fini(topo_mod_t *mod)
131{
132 topo_mod_unregister(mod);
133}
134
135boolean_t
136is_xpv(void)
137{
138 static int r = -1;
139 char platform[MAXNAMELEN];
140
141 if (r != -1)
142 return (r == 0);
143
144 (void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
145 r = strcmp(platform, "i86xpv");
146 return (r == 0);
147}
148
149static tnode_t *
150create_node(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, char *name,
151 topo_instance_t inst, nvlist_t *cpu, uint16_t smbios_id)
152{
153 nvlist_t *fmri;
154 tnode_t *cnode;
155
156 if (mkrsrc(mod, pnode, name, inst, auth, &fmri) != 0) {
157 whinge(mod, NULL, "create_node: mkrsrc failed\n");
158 return (NULL);
159 }
160
161 if (FM_AWARE_SMBIOS(mod)) {
162 id_t phys_cpu_smbid;
163 int perr = 0;
164 const char *serial = NULL;
165 const char *part = NULL;
166 const char *rev = NULL;
167
168 phys_cpu_smbid = smbios_id;
169 serial = chip_serial_smbios_get(mod, phys_cpu_smbid);
170 part = chip_part_smbios_get(mod, phys_cpu_smbid);
171 rev = chip_rev_smbios_get(mod, phys_cpu_smbid);
172
173 perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
174 serial);
175 perr += nvlist_add_string(fmri, FM_FMRI_HC_PART,
176 part);
177 perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION,
178 rev);
179
180 if (perr != 0)
181 whinge(mod, NULL,
182 "create_node: nvlist_add_string failed\n");
183
184 topo_mod_strfree(mod, (char *)serial);
185 topo_mod_strfree(mod, (char *)part);
186 topo_mod_strfree(mod, (char *)rev);
187 } else {
188 char *serial = NULL;
189
190 if (nvlist_lookup_string(cpu, FM_PHYSCPU_INFO_CHIP_IDENTSTR,
191 &serial) == 0) {
192 if (nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
193 serial) != 0) {
194 whinge(mod, NULL,
195 "create_node: nvlist_add_string failed\n");
196 }
197 }
198 }
199
200 cnode = topo_node_bind(mod, pnode, name, inst, fmri);
201
202 nvlist_free(fmri);
203 if (cnode == NULL) {
204 whinge(mod, NULL, "create_node: node bind failed"
205 " for %s %d\n", name, (int)inst);
206 }
207
208 return (cnode);
209}
210
211static int
212create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
213 nvlist_t *auth, uint16_t chip_smbiosid)
214{
215 tnode_t *strand;
216 int32_t strandid, cpuid;
217 int err, perr, nerr = 0;
218 nvlist_t *fmri;
219 char *serial = NULL;
220 char *part = NULL;
221 char *rev = NULL;
222
223 if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
224 &strandid)) != 0) {
225 whinge(mod, NULL, "create_strand: lookup strand_id failed: "
226 "%s\n", strerror(err));
227 return (-1);
228 }
229
230 if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid))
231 != NULL) {
232 whinge(mod, NULL, "create_strand: duplicate tuple found\n");
233 return (-1);
234 }
235
236 if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
237 strandid, cpu, chip_smbiosid)) == NULL)
238 return (-1);
239
240 /*
241 * Inherit FRU from core node, in native use cpu scheme ASRU,
242 * in xpv, use hc scheme ASRU.
243 */
244 (void) topo_node_fru_set(strand, NULL, 0, &perr);
245 /*
246 * From the inherited FRU, extract the Serial
247 * number(if SMBIOS donates) and set it in the ASRU
248 */
249 if (FM_AWARE_SMBIOS(mod)) {
250 char *val = NULL;
251
252 if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
253 TOPO_PROP_RESOURCE, &fmri, &err) != 0)
254 whinge(mod, NULL,
255 "create_strand: topo_prop_get_fmri failed\n");
256 if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0)
257 whinge(mod, NULL,
258 "create_strand: nvlist_lookup_string failed: \n");
259 else
260 serial = topo_mod_strdup(mod, val);
261 nvlist_free(fmri);
262 }
263 if (is_xpv()) {
264 if (topo_node_resource(strand, &fmri, &err) == -1) {
265 whinge(mod, &nerr, "create_strand: "
266 "topo_node_resource failed\n");
267 } else {
268 if (FM_AWARE_SMBIOS(mod))
269 (void) nvlist_add_string(fmri,
270 FM_FMRI_HC_SERIAL_ID, serial);
271 (void) topo_node_asru_set(strand, fmri, 0, &err);
272 nvlist_free(fmri);
273 }
274 } else {
275 if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
276 whinge(mod, &nerr, "create_strand: lookup cpuid "
277 "failed\n");
278 } else {
279 if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
280 != NULL) {
281 (void) topo_node_asru_set(strand, fmri,
282 0, &err);
283 nvlist_free(fmri);
284 } else {
285 whinge(mod, &nerr, "create_strand: "
286 "cpu_fmri_create() failed\n");
287 }
288 }
289 }
290
291 if (topo_method_register(mod, strand, strands_retire_methods) < 0)
292 whinge(mod, &nerr, "create_strand: "
293 "topo_method_register failed\n");
294
295 (void) topo_pgroup_create(strand, &strand_pgroup, &err);
296 nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
297 STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID,
298 NULL);
299
300 if (FM_AWARE_SMBIOS(mod)) {
301 (void) topo_node_label_set(strand, NULL, &perr);
302
303 if (topo_node_resource(strand, &fmri, &perr) != 0) {
304 whinge(mod, &nerr, "create_strand: "
305 "topo_node_resource failed\n");
306 perr = 0;
307 }
308
309 perr += nvlist_lookup_string(fmri,
310 FM_FMRI_HC_PART, &part);
311 perr += nvlist_lookup_string(fmri,
312 FM_FMRI_HC_REVISION, &rev);
313
314 if (perr != 0) {
315 whinge(mod, NULL,
316 "create_strand: nvlist_lookup_string failed\n");
317 perr = 0;
318 }
319
320 perr += topo_prop_set_string(strand, PGNAME(STRAND),
321 FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
322 perr += topo_prop_set_string(strand, PGNAME(STRAND),
323 FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
324 perr += topo_prop_set_string(strand, PGNAME(STRAND),
325 FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
326
327 if (perr != 0)
328 whinge(mod, NULL, "create_strand: topo_prop_set_string"
329 "failed\n");
330
331 nvlist_free(fmri);
332 topo_mod_strfree(mod, serial);
333 }
334
335 return (err == 0 && nerr == 0 ? 0 : -1);
336}
337
338static int
339create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
340 nvlist_t *auth, uint16_t chip_smbiosid)
341{
342 tnode_t *core;
343 int32_t coreid, cpuid;
344 int err, perr, nerr = 0;
345 nvlist_t *fmri;
346 char *serial = NULL;
347 char *part = NULL;
348 char *rev = NULL;
349
350 if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
351 != 0) {
352 whinge(mod, NULL, "create_core: lookup core_id failed: %s\n",
353 strerror(err));
354 return (-1);
355 }
356 if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
357 if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
358 coreid, cpu, chip_smbiosid)) == NULL)
359 return (-1);
360
361 /*
362 * Inherit FRU from the chip node, for native, we use hc
363 * scheme ASRU for the core node.
364 */
365 (void) topo_node_fru_set(core, NULL, 0, &perr);
366 /*
367 * From the inherited FRU, extract the Serial
368 * number if SMBIOS donates and set it in the ASRU
369 */
370 if (FM_AWARE_SMBIOS(mod)) {
371 char *val = NULL;
372
373 if (topo_node_resource(core, &fmri, &err) != 0)
374 whinge(mod, NULL,
375 "create_core: topo_prop_get_fmri failed\n");
376 if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID,
377 &val) != 0)
378 whinge(mod, NULL, "create_core:"
379 "nvlist_lookup_string failed\n");
380 else
381 serial = topo_mod_strdup(mod, val);
382 nvlist_free(fmri);
383 }
384 if (is_xpv()) {
385 if (topo_node_resource(core, &fmri, &err) == -1) {
386 whinge(mod, &nerr, "create_core: "
387 "topo_node_resource failed\n");
388 } else {
389 if (FM_AWARE_SMBIOS(mod))
390 (void) nvlist_add_string(fmri,
391 FM_FMRI_HC_SERIAL_ID, serial);
392 (void) topo_node_asru_set(core, fmri, 0, &err);
393 nvlist_free(fmri);
394 }
395 }
396 if (topo_method_register(mod, core, strands_retire_methods) < 0)
397 whinge(mod, &nerr, "create_core: "
398 "topo_method_register failed\n");
399
400 (void) topo_pgroup_create(core, &core_pgroup, &err);
401 nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL,
402 CORE_CHIP_ID, CORE_PROCNODE_ID, NULL);
403
404 if (topo_node_range_create(mod, core, STRAND_NODE_NAME,
405 0, 255) != 0)
406 return (-1);
407
408 /*
409 * Creating a temperature sensor may fail because the sensor
410 * doesn't exist or due to internal reasons. At the moment, we
411 * swallow any such errors that occur.
412 */
413 (void) chip_create_core_temp_sensor(mod, core);
414 }
415
416 if (!is_xpv()) {
417 /*
418 * In native mode, we're in favor of cpu scheme ASRU for
419 * printing reason. More work needs to be done to support
420 * multi-strand cpu: the ASRU will be a list of cpuid then.
421 */
422 if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
423 whinge(mod, &nerr, "create_core: lookup cpuid "
424 "failed\n");
425 } else {
426 if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
427 != NULL) {
428 (void) topo_node_asru_set(core, fmri, 0, &err);
429 nvlist_free(fmri);
430 } else {
431 whinge(mod, &nerr, "create_core: "
432 "cpu_fmri_create() failed\n");
433 }
434 }
435 }
436
437 if (FM_AWARE_SMBIOS(mod)) {
438 (void) topo_node_label_set(core, NULL, &perr);
439
440 if (topo_node_resource(core, &fmri, &perr) != 0) {
441 whinge(mod, &nerr, "create_core: "
442 "topo_node_resource failed\n");
443 perr = 0;
444 }
445
446 perr += nvlist_lookup_string(fmri,
447 FM_FMRI_HC_PART, &part);
448 perr += nvlist_lookup_string(fmri,
449 FM_FMRI_HC_REVISION, &rev);
450
451 if (perr != 0) {
452 whinge(mod, NULL,
453 "create_core: nvlist_lookup_string failed\n");
454 perr = 0;
455 }
456
457 perr += topo_prop_set_string(core, PGNAME(CORE),
458 FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
459 perr += topo_prop_set_string(core, PGNAME(CORE),
460 FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
461 perr += topo_prop_set_string(core, PGNAME(CORE),
462 FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
463
464 if (perr != 0)
465 whinge(mod, NULL, "create_core: topo_prop_set_string"
466 "failed\n");
467
468 nvlist_free(fmri);
469 topo_mod_strfree(mod, serial);
470 }
471
472 err = create_strand(mod, core, cpu, auth, chip_smbiosid);
473
474 return (err == 0 && nerr == 0 ? 0 : -1);
475}
476
477static int
478create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
479 topo_instance_t max, nvlist_t *cpu, nvlist_t *auth,
480 int mc_offchip, kstat_ctl_t *kc)
481{
482 tnode_t *chip;
483 nvlist_t *fmri = NULL;
484 int err, perr, nerr = 0;
485 int32_t chipid, procnodeid, procnodes_per_pkg;
485 const char *vendor, *brand;
486 const char *vendor;
487 char *brand, *socket;
486 int32_t family, model;
487 boolean_t create_mc = B_FALSE;
488 uint16_t smbios_id;
489
490 /*
491 * /dev/fm will export the chipid based on SMBIOS' ordering
492 * of Type-4 structures, if SMBIOS meets FMA needs
493 */
494 err = nvlist_lookup_pairs(cpu, 0,
495 FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32, &chipid,
496 FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32, &procnodes_per_pkg,
497 FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32, &procnodeid,
498 FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING, &vendor,
499 FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32, &family,
500 FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32, &model,
501 NULL);
502
503 if (err) {
504 whinge(mod, NULL, "create_chip: lookup failed: %s\n",
505 strerror(err));
506 return (-1);
507 }
508
509 if (chipid < min || chipid > max)
510 return (-1);
511
512 if (FM_AWARE_SMBIOS(mod)) {
513 if ((err = nvlist_lookup_uint16(cpu,
514 FM_PHYSCPU_INFO_SMBIOS_ID, &smbios_id)) != 0) {
515 whinge(mod, NULL,
516 "create_chip: lookup smbios_id failed"
517 ": enumerating x86pi & chip topology, but"
518 " no Chip properties from SMBIOS"
519 " - err msg : %s\n", strerror(err));
520 /*
521 * Lets reset the module specific
522 * data to NULL, overriding any
523 * SMBIOS capability encoded earlier.
524 * This will fail all subsequent
525 * FM_AWARE_SMBIOS checks.
526 */
527 topo_mod_setspecific(mod, NULL);
528 }
529 }
530
531 if ((chip = topo_node_lookup(pnode, CHIP_NODE_NAME, chipid)) == NULL) {
532 if ((chip = create_node(mod, pnode, auth, CHIP_NODE_NAME,
533 chipid, cpu, smbios_id)) == NULL)
534 return (-1);
535 /*
536 * Do not register XML map methods if SMBIOS can provide
537 * serial, part, revision & label
538 */
539 if (!FM_AWARE_SMBIOS(mod)) {
540 if (topo_method_register(mod, chip, chip_methods) < 0)
541 whinge(mod, &nerr, "create_chip: "
542 "topo_method_register failed\n");
543 }
544
545 (void) topo_pgroup_create(chip, &chip_pgroup, &err);
546 nerr -= add_nvlist_strprop(mod, chip, cpu, PGNAME(CHIP),
547 CHIP_VENDOR_ID, NULL);
548 nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP),
549 NULL, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL);
550
551 /*
488 int32_t family, model;
489 boolean_t create_mc = B_FALSE;
490 uint16_t smbios_id;
491
492 /*
493 * /dev/fm will export the chipid based on SMBIOS' ordering
494 * of Type-4 structures, if SMBIOS meets FMA needs
495 */
496 err = nvlist_lookup_pairs(cpu, 0,
497 FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32, &chipid,
498 FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32, &procnodes_per_pkg,
499 FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32, &procnodeid,
500 FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING, &vendor,
501 FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32, &family,
502 FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32, &model,
503 NULL);
504
505 if (err) {
506 whinge(mod, NULL, "create_chip: lookup failed: %s\n",
507 strerror(err));
508 return (-1);
509 }
510
511 if (chipid < min || chipid > max)
512 return (-1);
513
514 if (FM_AWARE_SMBIOS(mod)) {
515 if ((err = nvlist_lookup_uint16(cpu,
516 FM_PHYSCPU_INFO_SMBIOS_ID, &smbios_id)) != 0) {
517 whinge(mod, NULL,
518 "create_chip: lookup smbios_id failed"
519 ": enumerating x86pi & chip topology, but"
520 " no Chip properties from SMBIOS"
521 " - err msg : %s\n", strerror(err));
522 /*
523 * Lets reset the module specific
524 * data to NULL, overriding any
525 * SMBIOS capability encoded earlier.
526 * This will fail all subsequent
527 * FM_AWARE_SMBIOS checks.
528 */
529 topo_mod_setspecific(mod, NULL);
530 }
531 }
532
533 if ((chip = topo_node_lookup(pnode, CHIP_NODE_NAME, chipid)) == NULL) {
534 if ((chip = create_node(mod, pnode, auth, CHIP_NODE_NAME,
535 chipid, cpu, smbios_id)) == NULL)
536 return (-1);
537 /*
538 * Do not register XML map methods if SMBIOS can provide
539 * serial, part, revision & label
540 */
541 if (!FM_AWARE_SMBIOS(mod)) {
542 if (topo_method_register(mod, chip, chip_methods) < 0)
543 whinge(mod, &nerr, "create_chip: "
544 "topo_method_register failed\n");
545 }
546
547 (void) topo_pgroup_create(chip, &chip_pgroup, &err);
548 nerr -= add_nvlist_strprop(mod, chip, cpu, PGNAME(CHIP),
549 CHIP_VENDOR_ID, NULL);
550 nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP),
551 NULL, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL);
552
553 /*
552 * Attempt to lookup the processor brand string in kstats.
553 * and add it as a prop, if found.
554 * Attempt to lookup the processor brand and socket string in
555 * kstats and add it as a prop, if found.
554 */
556 */
555 brand = get_chip_brand(mod, kc, chipid);
557 brand = socket = NULL;
558 get_chip_kstat_strs(mod, kc, chipid, &brand, &socket);
556 if (brand != NULL && topo_prop_set_string(chip, PGNAME(CHIP),
557 CHIP_BRAND, TOPO_PROP_IMMUTABLE, brand, &perr) != 0) {
558 whinge(mod, &nerr, "failed to set prop %s/%s",
559 PGNAME(CHIP), CHIP_BRAND);
560 }
559 if (brand != NULL && topo_prop_set_string(chip, PGNAME(CHIP),
560 CHIP_BRAND, TOPO_PROP_IMMUTABLE, brand, &perr) != 0) {
561 whinge(mod, &nerr, "failed to set prop %s/%s",
562 PGNAME(CHIP), CHIP_BRAND);
563 }
561 topo_mod_strfree(mod, (char *)brand);
564 topo_mod_strfree(mod, brand);
562
565
566 if (socket != NULL && topo_prop_set_string(chip, PGNAME(CHIP),
567 CHIP_SOCKET, TOPO_PROP_IMMUTABLE, socket, &perr) != 0) {
568 whinge(mod, &nerr, "failed to set prop %s/%s",
569 PGNAME(CHIP), CHIP_SOCKET);
570 }
571 topo_mod_strfree(mod, socket);
572
563 if (FM_AWARE_SMBIOS(mod)) {
564 int fru = 0;
565 char *serial = NULL;
566 char *part = NULL;
567 char *rev = NULL;
568 char *label;
569
570 fru = chip_fru_smbios_get(mod, smbios_id);
571 /*
572 * Chip is not a FRU, set the FRU fmri of parent node
573 */
574 if (topo_node_resource(chip, &fmri, &perr) != 0)
575 whinge(mod, &nerr, "create_chip: "
576 "topo_node_resource failed\n");
577 if (!fru) {
578 (void) topo_node_fru_set(chip, NULL, 0, &perr);
579 label = NULL;
580 } else {
581 label = (char *)chip_label_smbios_get(mod,
582 pnode, smbios_id, NULL);
583
584 if (topo_node_fru_set(chip, fmri, 0, &perr)
585 != 0) {
586 whinge(mod, NULL, "create_chip: "
587 "topo_node_fru_set failed\n");
588 perr = 0;
589 }
590 }
591
592 perr += nvlist_lookup_string(fmri,
593 FM_FMRI_HC_SERIAL_ID, &serial);
594 perr += nvlist_lookup_string(fmri,
595 FM_FMRI_HC_PART, &part);
596 perr += nvlist_lookup_string(fmri,
597 FM_FMRI_HC_REVISION, &rev);
598
599 if (perr != 0) {
600 whinge(mod, NULL,
601 "create_chip: nvlist_lookup_string"
602 "failed\n");
603 perr = 0;
604 }
605
606 perr += topo_prop_set_string(chip, PGNAME(CHIP),
607 FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
608 serial, &perr);
609 perr += topo_prop_set_string(chip, PGNAME(CHIP),
610 FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
611 part, &perr);
612 perr += topo_prop_set_string(chip, PGNAME(CHIP),
613 FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
614 rev, &perr);
615
616 if (perr != 0)
617 whinge(mod, NULL,
618 "create_chip: topo_prop_set_string"
619 "failed\n");
620
621 nvlist_free(fmri);
622
623 if (topo_node_label_set(chip, label, &perr)
624 == -1) {
625 whinge(mod, NULL, "create_chip: "
626 "topo_node_label_set failed\n");
627 }
628 topo_mod_strfree(mod, label);
629
630 } else {
631 if (topo_node_resource(chip, &fmri, &err) == -1) {
632 whinge(mod, &nerr, "create_chip: "
633 "topo_node_resource failed\n");
634 } else {
635 (void) topo_node_fru_set(chip, fmri, 0, &perr);
636 nvlist_free(fmri);
637 }
638 }
639
640 if (topo_method_register(mod, chip, strands_retire_methods) < 0)
641 whinge(mod, &nerr, "create_chip: "
642 "topo_method_register failed\n");
643
644 if (topo_node_range_create(mod, chip, CORE_NODE_NAME, 0, 255))
645 return (-1);
646
647 if (strcmp(vendor, "AuthenticAMD") == 0) {
648 if (topo_node_range_create(mod, chip, MCT_NODE_NAME,
649 0, 255))
650 return (-1);
651 }
652
653 create_mc = B_TRUE;
654
655 /*
656 * Creating a temperature sensor may fail because the sensor
657 * doesn't exist or due to internal reasons. At the moment, we
658 * swallow any such errors that occur.
659 */
660 (void) chip_create_chip_temp_sensor(mod, chip);
661 }
662
663 if (FM_AWARE_SMBIOS(mod)) {
664 int status = 0;
665 /*
666 * STATUS
667 * CPU Socket Populated
668 * CPU Socket Unpopulated
669 * Populated : Enabled
670 * Populated : Disabled by BIOS (Setup)
671 * Populated : Disabled by BIOS (Error)
672 * Populated : Idle
673 *
674 * Enumerate core & strand only for Populated : Enabled
675 * Enumerate Off-Chip Memory Controller only for
676 * Populated : Enabled
677 */
678
679 status = chip_status_smbios_get(mod, (id_t)smbios_id);
680 if (!status) {
681 whinge(mod, NULL, "create_chip: "
682 "CPU Socket is not populated or is disabled\n");
683 return (0);
684 }
685 }
686
687 err = create_core(mod, chip, cpu, auth, smbios_id);
688
689 /*
690 * Create memory-controller node under a chip for architectures
691 * that may have on-chip memory-controller(s).
692 * If SMBIOS meets FMA needs, when Multi-Chip-Module is
693 * addressed, mc instances should be derived from SMBIOS
694 */
695 if (strcmp(vendor, "AuthenticAMD") == 0) {
696 amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth,
697 procnodeid, procnodes_per_pkg, family, model, &nerr);
698 } else if (create_mc && !mc_offchip)
699 onchip_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth);
700
701 return (err == 0 && nerr == 0 ? 0 : -1);
702}
703
704/*ARGSUSED*/
705static int
706create_chips(topo_mod_t *mod, tnode_t *pnode, const char *name,
707 topo_instance_t min, topo_instance_t max, void *arg, nvlist_t *auth,
708 int mc_offchip)
709{
710 fmd_agent_hdl_t *hdl;
711 nvlist_t **cpus;
712 int nerr = 0;
713 uint_t i, ncpu;
714 kstat_ctl_t *kc;
715
716 if (strcmp(name, CHIP_NODE_NAME) != 0)
717 return (0);
718
719 if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL)
720 return (-1);
721 if (fmd_agent_physcpu_info(hdl, &cpus, &ncpu) != 0) {
722 whinge(mod, NULL, "create_chip: fmd_agent_physcpu_info "
723 "failed: %s\n", fmd_agent_errmsg(hdl));
724 fmd_agent_close(hdl);
725 return (-1);
726 }
727 fmd_agent_close(hdl);
728
729 if ((kc = kstat_open()) == NULL) {
730 whinge(mod, NULL, "kstat_open() failed");
731 return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
732 }
733
734 for (i = 0; i < ncpu; i++) {
735 nerr -= create_chip(mod, pnode, min, max, cpus[i], auth,
736 mc_offchip, kc);
737 nvlist_free(cpus[i]);
738 }
739 (void) kstat_close(kc);
740 umem_free(cpus, sizeof (nvlist_t *) * ncpu);
741
742 if (nerr == 0) {
743 return (0);
744 } else {
745 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
746 return (-1);
747 }
748}
749
750/*ARGSUSED*/
751static int
752chip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
753 topo_instance_t min, topo_instance_t max, void *arg, void *smbios_enabled)
754{
755 int rv = 0;
756 nvlist_t *auth = NULL;
757 int offchip_mc;
758 char buf[BUFSIZ];
759 const char *dom0 = "control_d";
760
761 /*
762 * Create nothing if we're running in domU.
763 */
764 if (sysinfo(SI_PLATFORM, buf, sizeof (buf)) == -1)
765 return (-1);
766
767 if (strncmp(buf, "i86pc", sizeof (buf)) != 0 &&
768 strncmp(buf, "i86xpv", sizeof (buf)) != 0)
769 return (0);
770
771 if (strncmp(buf, "i86xpv", sizeof (buf)) == 0) {
772 int fd = open("/dev/xen/domcaps", O_RDONLY);
773
774 if (fd != -1) {
775 if (read(fd, buf, sizeof (buf)) <= 0 ||
776 strncmp(buf, dom0, strlen(dom0)) != 0) {
777 (void) close(fd);
778 return (0);
779 }
780 (void) close(fd);
781 }
782 }
783
784 /*
785 * Set Chip Enumerator Module's private data with the value passed by
786 * x86pi Enumerator, defining SMBIOS capabilities
787 */
788 topo_mod_setspecific(mod, smbios_enabled);
789
790 if (FM_AWARE_SMBIOS(mod))
791 if (init_chip_smbios(mod) != 0) {
792 whinge(mod, NULL,
793 "init_chip_smbios() failed, "
794 " enumerating x86pi & chip topology, but no"
795 " CPU & Memory properties will be"
796 " derived from SMBIOS\n");
797 /*
798 * Lets reset the module specific
799 * data to NULL, overriding any
800 * SMBIOS capability encoded earlier.
801 * This will fail all subsequent
802 * FM_AWARE_SMBIOS checks.
803 */
804 topo_mod_setspecific(mod, NULL);
805 }
806
807 auth = topo_mod_auth(mod, pnode);
808
809 offchip_mc = mc_offchip_open();
810 if (strcmp(name, CHIP_NODE_NAME) == 0)
811 rv = create_chips(mod, pnode, name, min, max, NULL, auth,
812 offchip_mc);
813
814 if (offchip_mc)
815 (void) mc_offchip_create(mod, pnode, "memory-controller", auth);
816
817 nvlist_free(auth);
818
819 return (rv);
820}
573 if (FM_AWARE_SMBIOS(mod)) {
574 int fru = 0;
575 char *serial = NULL;
576 char *part = NULL;
577 char *rev = NULL;
578 char *label;
579
580 fru = chip_fru_smbios_get(mod, smbios_id);
581 /*
582 * Chip is not a FRU, set the FRU fmri of parent node
583 */
584 if (topo_node_resource(chip, &fmri, &perr) != 0)
585 whinge(mod, &nerr, "create_chip: "
586 "topo_node_resource failed\n");
587 if (!fru) {
588 (void) topo_node_fru_set(chip, NULL, 0, &perr);
589 label = NULL;
590 } else {
591 label = (char *)chip_label_smbios_get(mod,
592 pnode, smbios_id, NULL);
593
594 if (topo_node_fru_set(chip, fmri, 0, &perr)
595 != 0) {
596 whinge(mod, NULL, "create_chip: "
597 "topo_node_fru_set failed\n");
598 perr = 0;
599 }
600 }
601
602 perr += nvlist_lookup_string(fmri,
603 FM_FMRI_HC_SERIAL_ID, &serial);
604 perr += nvlist_lookup_string(fmri,
605 FM_FMRI_HC_PART, &part);
606 perr += nvlist_lookup_string(fmri,
607 FM_FMRI_HC_REVISION, &rev);
608
609 if (perr != 0) {
610 whinge(mod, NULL,
611 "create_chip: nvlist_lookup_string"
612 "failed\n");
613 perr = 0;
614 }
615
616 perr += topo_prop_set_string(chip, PGNAME(CHIP),
617 FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
618 serial, &perr);
619 perr += topo_prop_set_string(chip, PGNAME(CHIP),
620 FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
621 part, &perr);
622 perr += topo_prop_set_string(chip, PGNAME(CHIP),
623 FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
624 rev, &perr);
625
626 if (perr != 0)
627 whinge(mod, NULL,
628 "create_chip: topo_prop_set_string"
629 "failed\n");
630
631 nvlist_free(fmri);
632
633 if (topo_node_label_set(chip, label, &perr)
634 == -1) {
635 whinge(mod, NULL, "create_chip: "
636 "topo_node_label_set failed\n");
637 }
638 topo_mod_strfree(mod, label);
639
640 } else {
641 if (topo_node_resource(chip, &fmri, &err) == -1) {
642 whinge(mod, &nerr, "create_chip: "
643 "topo_node_resource failed\n");
644 } else {
645 (void) topo_node_fru_set(chip, fmri, 0, &perr);
646 nvlist_free(fmri);
647 }
648 }
649
650 if (topo_method_register(mod, chip, strands_retire_methods) < 0)
651 whinge(mod, &nerr, "create_chip: "
652 "topo_method_register failed\n");
653
654 if (topo_node_range_create(mod, chip, CORE_NODE_NAME, 0, 255))
655 return (-1);
656
657 if (strcmp(vendor, "AuthenticAMD") == 0) {
658 if (topo_node_range_create(mod, chip, MCT_NODE_NAME,
659 0, 255))
660 return (-1);
661 }
662
663 create_mc = B_TRUE;
664
665 /*
666 * Creating a temperature sensor may fail because the sensor
667 * doesn't exist or due to internal reasons. At the moment, we
668 * swallow any such errors that occur.
669 */
670 (void) chip_create_chip_temp_sensor(mod, chip);
671 }
672
673 if (FM_AWARE_SMBIOS(mod)) {
674 int status = 0;
675 /*
676 * STATUS
677 * CPU Socket Populated
678 * CPU Socket Unpopulated
679 * Populated : Enabled
680 * Populated : Disabled by BIOS (Setup)
681 * Populated : Disabled by BIOS (Error)
682 * Populated : Idle
683 *
684 * Enumerate core & strand only for Populated : Enabled
685 * Enumerate Off-Chip Memory Controller only for
686 * Populated : Enabled
687 */
688
689 status = chip_status_smbios_get(mod, (id_t)smbios_id);
690 if (!status) {
691 whinge(mod, NULL, "create_chip: "
692 "CPU Socket is not populated or is disabled\n");
693 return (0);
694 }
695 }
696
697 err = create_core(mod, chip, cpu, auth, smbios_id);
698
699 /*
700 * Create memory-controller node under a chip for architectures
701 * that may have on-chip memory-controller(s).
702 * If SMBIOS meets FMA needs, when Multi-Chip-Module is
703 * addressed, mc instances should be derived from SMBIOS
704 */
705 if (strcmp(vendor, "AuthenticAMD") == 0) {
706 amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth,
707 procnodeid, procnodes_per_pkg, family, model, &nerr);
708 } else if (create_mc && !mc_offchip)
709 onchip_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth);
710
711 return (err == 0 && nerr == 0 ? 0 : -1);
712}
713
714/*ARGSUSED*/
715static int
716create_chips(topo_mod_t *mod, tnode_t *pnode, const char *name,
717 topo_instance_t min, topo_instance_t max, void *arg, nvlist_t *auth,
718 int mc_offchip)
719{
720 fmd_agent_hdl_t *hdl;
721 nvlist_t **cpus;
722 int nerr = 0;
723 uint_t i, ncpu;
724 kstat_ctl_t *kc;
725
726 if (strcmp(name, CHIP_NODE_NAME) != 0)
727 return (0);
728
729 if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL)
730 return (-1);
731 if (fmd_agent_physcpu_info(hdl, &cpus, &ncpu) != 0) {
732 whinge(mod, NULL, "create_chip: fmd_agent_physcpu_info "
733 "failed: %s\n", fmd_agent_errmsg(hdl));
734 fmd_agent_close(hdl);
735 return (-1);
736 }
737 fmd_agent_close(hdl);
738
739 if ((kc = kstat_open()) == NULL) {
740 whinge(mod, NULL, "kstat_open() failed");
741 return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
742 }
743
744 for (i = 0; i < ncpu; i++) {
745 nerr -= create_chip(mod, pnode, min, max, cpus[i], auth,
746 mc_offchip, kc);
747 nvlist_free(cpus[i]);
748 }
749 (void) kstat_close(kc);
750 umem_free(cpus, sizeof (nvlist_t *) * ncpu);
751
752 if (nerr == 0) {
753 return (0);
754 } else {
755 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
756 return (-1);
757 }
758}
759
760/*ARGSUSED*/
761static int
762chip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
763 topo_instance_t min, topo_instance_t max, void *arg, void *smbios_enabled)
764{
765 int rv = 0;
766 nvlist_t *auth = NULL;
767 int offchip_mc;
768 char buf[BUFSIZ];
769 const char *dom0 = "control_d";
770
771 /*
772 * Create nothing if we're running in domU.
773 */
774 if (sysinfo(SI_PLATFORM, buf, sizeof (buf)) == -1)
775 return (-1);
776
777 if (strncmp(buf, "i86pc", sizeof (buf)) != 0 &&
778 strncmp(buf, "i86xpv", sizeof (buf)) != 0)
779 return (0);
780
781 if (strncmp(buf, "i86xpv", sizeof (buf)) == 0) {
782 int fd = open("/dev/xen/domcaps", O_RDONLY);
783
784 if (fd != -1) {
785 if (read(fd, buf, sizeof (buf)) <= 0 ||
786 strncmp(buf, dom0, strlen(dom0)) != 0) {
787 (void) close(fd);
788 return (0);
789 }
790 (void) close(fd);
791 }
792 }
793
794 /*
795 * Set Chip Enumerator Module's private data with the value passed by
796 * x86pi Enumerator, defining SMBIOS capabilities
797 */
798 topo_mod_setspecific(mod, smbios_enabled);
799
800 if (FM_AWARE_SMBIOS(mod))
801 if (init_chip_smbios(mod) != 0) {
802 whinge(mod, NULL,
803 "init_chip_smbios() failed, "
804 " enumerating x86pi & chip topology, but no"
805 " CPU & Memory properties will be"
806 " derived from SMBIOS\n");
807 /*
808 * Lets reset the module specific
809 * data to NULL, overriding any
810 * SMBIOS capability encoded earlier.
811 * This will fail all subsequent
812 * FM_AWARE_SMBIOS checks.
813 */
814 topo_mod_setspecific(mod, NULL);
815 }
816
817 auth = topo_mod_auth(mod, pnode);
818
819 offchip_mc = mc_offchip_open();
820 if (strcmp(name, CHIP_NODE_NAME) == 0)
821 rv = create_chips(mod, pnode, name, min, max, NULL, auth,
822 offchip_mc);
823
824 if (offchip_mc)
825 (void) mc_offchip_create(mod, pnode, "memory-controller", auth);
826
827 nvlist_free(auth);
828
829 return (rv);
830}