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 */ 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 64 static int chip_enum(topo_mod_t *, tnode_t *, const char *, 65 topo_instance_t, topo_instance_t, void *, void *); 66 67 static const topo_modops_t chip_ops = 68 { chip_enum, NULL}; 69 static const topo_modinfo_t chip_info = 70 { CHIP_NODE_NAME, FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops }; 71 72 static const topo_pgroup_info_t chip_pgroup = 73 { PGNAME(CHIP), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; 74 75 static const topo_pgroup_info_t core_pgroup = 76 { PGNAME(CORE), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; 77 78 static const topo_pgroup_info_t strand_pgroup = 79 { PGNAME(STRAND), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; 80 81 static 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 96 static 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 112 int 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 128 void 129 _topo_fini(topo_mod_t *mod) 130 { 131 topo_mod_unregister(mod); 132 } 133 134 boolean_t 135 is_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 148 static tnode_t * 149 create_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 210 static int 211 create_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 337 static int 338 create_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 476 static int 477 create_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; 485 const char *vendor, *brand; 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 /* 552 * Attempt to lookup the processor brand string in kstats. 553 * and add it as a prop, if found. 554 */ 555 brand = get_chip_brand(mod, kc, chipid); 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 } 561 topo_mod_strfree(mod, (char *)brand); 562 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*/ 705 static int 706 create_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*/ 751 static int 752 chip_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 } 821