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 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 65 static int chip_enum(topo_mod_t *, tnode_t *, const char *, 66 topo_instance_t, topo_instance_t, void *, void *); 67 68 static const topo_modops_t chip_ops = 69 { chip_enum, NULL}; 70 static const topo_modinfo_t chip_info = 71 { CHIP_NODE_NAME, FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops }; 72 73 static const topo_pgroup_info_t chip_pgroup = 74 { PGNAME(CHIP), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; 75 76 static const topo_pgroup_info_t core_pgroup = 77 { PGNAME(CORE), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; 78 79 static const topo_pgroup_info_t strand_pgroup = 80 { PGNAME(STRAND), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; 81 82 static 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 97 static 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 113 int 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 129 void 130 _topo_fini(topo_mod_t *mod) 131 { 132 topo_mod_unregister(mod); 133 } 134 135 boolean_t 136 is_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 149 static tnode_t * 150 create_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 211 static int 212 create_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 338 static int 339 create_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 477 static int 478 create_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; 486 const char *vendor; 487 char *brand, *socket; 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 /* 554 * Attempt to lookup the processor brand and socket string in 555 * kstats and add it as a prop, if found. 556 */ 557 brand = socket = NULL; 558 get_chip_kstat_strs(mod, kc, chipid, &brand, &socket); 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 } 564 topo_mod_strfree(mod, brand); 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 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*/ 715 static int 716 create_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*/ 761 static int 762 chip_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 } 831