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