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 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 125 _topo_fini(topo_mod_t *mod) 126 { 127 topo_mod_unregister(mod); 128 } 129 130 boolean_t 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 * 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 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 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 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 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 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