2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <unistd.h>
2N/A#include <fcntl.h>
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <stdarg.h>
2N/A#include <string.h>
2N/A#include <strings.h>
2N/A#include <limits.h>
2N/A#include <alloca.h>
2N/A#include <kstat.h>
2N/A#include <errno.h>
2N/A#include <libnvpair.h>
2N/A#include <sys/types.h>
2N/A#include <sys/bitmap.h>
2N/A#include <sys/processor.h>
2N/A#include <sys/param.h>
2N/A#include <sys/fm/protocol.h>
2N/A#include <sys/systeminfo.h>
2N/A#include <sys/mc.h>
2N/A#include <sys/mc_amd.h>
2N/A#include <sys/mc_intel.h>
2N/A#include <sys/devfm.h>
2N/A#include <fm/fmd_agent.h>
2N/A#include <fm/topo_mod.h>
2N/A
2N/A#include "chip.h"
2N/A
2N/A#define MAX_DIMMNUM 7
2N/A#define MAX_CSNUM 7
2N/A
2N/A/*
2N/A * Enumerates the processing chips, or sockets, (as distinct from cores) in a
2N/A * system. For each chip found, the necessary nodes (one or more cores, and
2N/A * possibly a memory controller) are constructed underneath.
2N/A */
2N/A
2N/Astatic int chip_enum(topo_mod_t *, tnode_t *, const char *,
2N/A topo_instance_t, topo_instance_t, void *, void *);
2N/A
2N/Astatic const topo_modops_t chip_ops =
2N/A { chip_enum, NULL};
2N/Astatic const topo_modinfo_t chip_info =
2N/A { CHIP_NODE_NAME, FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops };
2N/A
2N/Astatic const topo_pgroup_info_t chip_pgroup =
2N/A { PGNAME(CHIP), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
2N/A
2N/Astatic const topo_pgroup_info_t core_pgroup =
2N/A { PGNAME(CORE), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
2N/A
2N/Astatic const topo_pgroup_info_t strand_pgroup =
2N/A { PGNAME(STRAND), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
2N/A
2N/Astatic const topo_method_t chip_methods[] = {
2N/A { SIMPLE_CHIP_LBL, "Property method", 0,
2N/A TOPO_STABILITY_INTERNAL, simple_chip_label},
2N/A { G4_CHIP_LBL, "Property method", 0,
2N/A TOPO_STABILITY_INTERNAL, g4_chip_label},
2N/A { A4FPLUS_CHIP_LBL, "Property method", 0,
2N/A TOPO_STABILITY_INTERNAL, a4fplus_chip_label},
2N/A { FSB2_CHIP_LBL, "Property method", 0,
2N/A TOPO_STABILITY_INTERNAL, fsb2_chip_label},
2N/A { NULL }
2N/A};
2N/A
2N/Astatic const topo_method_t strands_retire_methods[] = {
2N/A { TOPO_METH_RETIRE, TOPO_METH_RETIRE_DESC,
2N/A TOPO_METH_RETIRE_VERSION, TOPO_STABILITY_INTERNAL,
2N/A retire_strands },
2N/A { TOPO_METH_UNRETIRE, TOPO_METH_UNRETIRE_DESC,
2N/A TOPO_METH_UNRETIRE_VERSION, TOPO_STABILITY_INTERNAL,
2N/A unretire_strands },
2N/A { TOPO_METH_SERVICE_STATE, TOPO_METH_SERVICE_STATE_DESC,
2N/A TOPO_METH_SERVICE_STATE_VERSION, TOPO_STABILITY_INTERNAL,
2N/A service_state_strands },
2N/A { NULL }
2N/A};
2N/A
2N/A/* ID counts for SMBIOS structures */
2N/Aint ncpu_ids;
2N/Aint bb_count;
2N/Aint ndimm_ids;
2N/Aint nmct_ids;
2N/A
2N/Aint
2N/A_topo_init(topo_mod_t *mod)
2N/A{
2N/A if (getenv("TOPOCHIPDBG"))
2N/A topo_mod_setdebug(mod);
2N/A topo_mod_dprintf(mod, "initializing chip enumerator\n");
2N/A
2N/A if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
2N/A whinge(mod, NULL, "failed to register hc: "
2N/A "%s\n", topo_mod_errmsg(mod));
2N/A return (-1); /* mod errno set */
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Avoid
2N/A_topo_fini(topo_mod_t *mod)
2N/A{
2N/A topo_mod_unregister(mod);
2N/A}
2N/A
2N/Aboolean_t
2N/Ais_xpv(void)
2N/A{
2N/A static int r = -1;
2N/A char platform[MAXNAMELEN];
2N/A
2N/A if (r != -1)
2N/A return (r == 0);
2N/A
2N/A (void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
2N/A r = strcmp(platform, "i86xpv");
2N/A return (r == 0);
2N/A}
2N/A
2N/Astatic tnode_t *
2N/Acreate_node(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, char *name,
2N/A topo_instance_t inst, uint16_t smbios_id)
2N/A{
2N/A nvlist_t *fmri;
2N/A tnode_t *cnode;
2N/A
2N/A if (mkrsrc(mod, pnode, name, inst, auth, &fmri) != 0) {
2N/A whinge(mod, NULL, "create_node: mkrsrc failed\n");
2N/A return (NULL);
2N/A }
2N/A
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A id_t phys_cpu_smbid;
2N/A int perr = 0;
2N/A const char *serial = NULL;
2N/A const char *part = NULL;
2N/A const char *rev = NULL;
2N/A
2N/A phys_cpu_smbid = smbios_id;
2N/A serial = chip_serial_smbios_get(mod, phys_cpu_smbid);
2N/A part = chip_part_smbios_get(mod, phys_cpu_smbid);
2N/A rev = chip_rev_smbios_get(mod, phys_cpu_smbid);
2N/A
2N/A perr += nvlist_add_string(fmri, FM_FMRI_HC_V1_FRU_SN,
2N/A serial);
2N/A perr += nvlist_add_string(fmri, FM_FMRI_HC_V1_FRU_PN,
2N/A part);
2N/A perr += nvlist_add_string(fmri, FM_FMRI_HC_V1_FRU_REV,
2N/A rev);
2N/A
2N/A if (perr != 0)
2N/A whinge(mod, NULL,
2N/A "create_node: nvlist_add_string failed\n");
2N/A
2N/A topo_mod_strfree(mod, (char *)serial);
2N/A topo_mod_strfree(mod, (char *)part);
2N/A topo_mod_strfree(mod, (char *)rev);
2N/A }
2N/A
2N/A cnode = topo_node_bind(mod, pnode, name, inst, fmri);
2N/A
2N/A nvlist_free(fmri);
2N/A if (cnode == NULL) {
2N/A whinge(mod, NULL, "create_node: node bind failed"
2N/A " for %s %d\n", name, (int)inst);
2N/A }
2N/A
2N/A return (cnode);
2N/A}
2N/A
2N/Astatic int
2N/Acreate_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
2N/A nvlist_t *auth, uint16_t chip_smbiosid)
2N/A{
2N/A tnode_t *strand;
2N/A int32_t strandid, cpuid;
2N/A int err, perr, nerr = 0;
2N/A nvlist_t *fmri;
2N/A char *serial = NULL;
2N/A char *part = NULL;
2N/A char *rev = NULL;
2N/A
2N/A if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
2N/A &strandid)) != 0) {
2N/A whinge(mod, NULL, "create_strand: lookup strand_id failed: "
2N/A "%s\n", strerror(err));
2N/A return (-1);
2N/A }
2N/A
2N/A if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid))
2N/A != NULL) {
2N/A whinge(mod, NULL, "create_strand: duplicate tuple found\n");
2N/A return (-1);
2N/A }
2N/A
2N/A if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
2N/A strandid, chip_smbiosid)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Inherit FRU from core node, in native use cpu scheme ASRU,
2N/A * in xpv, use hc scheme ASRU.
2N/A */
2N/A (void) topo_node_fru_set(strand, NULL, 0, &perr);
2N/A /*
2N/A * From the inherited FRU, extract the Serial
2N/A * number(if SMBIOS donates) and set it in the ASRU
2N/A */
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A char *val = NULL;
2N/A
2N/A if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
2N/A TOPO_PROP_RESOURCE, &fmri, &err) != 0)
2N/A whinge(mod, NULL,
2N/A "create_strand: topo_prop_get_fmri failed\n");
2N/A if (nvlist_lookup_string(fmri, FM_FMRI_HC_V1_FRU_SN, &val) != 0)
2N/A whinge(mod, NULL,
2N/A "create_strand: nvlist_lookup_string failed: \n");
2N/A else
2N/A serial = topo_mod_strdup(mod, val);
2N/A nvlist_free(fmri);
2N/A }
2N/A if (is_xpv()) {
2N/A if (topo_node_resource(strand, &fmri, &err) == -1) {
2N/A whinge(mod, &nerr, "create_strand: "
2N/A "topo_node_resource failed\n");
2N/A } else {
2N/A if (FM_AWARE_SMBIOS(mod))
2N/A (void) nvlist_add_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_SN, serial);
2N/A (void) topo_node_asru_set(strand, fmri, 0, &err);
2N/A nvlist_free(fmri);
2N/A }
2N/A } else {
2N/A if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
2N/A whinge(mod, &nerr, "create_strand: lookup cpuid "
2N/A "failed\n");
2N/A } else {
2N/A if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
2N/A != NULL) {
2N/A (void) topo_node_asru_set(strand, fmri,
2N/A 0, &err);
2N/A nvlist_free(fmri);
2N/A } else {
2N/A whinge(mod, &nerr, "create_strand: "
2N/A "cpu_fmri_create() failed\n");
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (topo_method_register(mod, strand, strands_retire_methods) < 0)
2N/A whinge(mod, &nerr, "create_strand: "
2N/A "topo_method_register failed\n");
2N/A
2N/A (void) topo_pgroup_create(strand, &strand_pgroup, &err);
2N/A nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
2N/A STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID,
2N/A NULL);
2N/A
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A (void) topo_node_label_set(strand, NULL, &perr);
2N/A
2N/A if (topo_node_resource(strand, &fmri, &perr) != 0) {
2N/A whinge(mod, &nerr, "create_strand: "
2N/A "topo_node_resource failed\n");
2N/A perr = 0;
2N/A }
2N/A
2N/A perr += nvlist_lookup_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_PN, &part);
2N/A perr += nvlist_lookup_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_REV, &rev);
2N/A
2N/A if (perr != 0) {
2N/A whinge(mod, NULL,
2N/A "create_strand: nvlist_lookup_string failed\n");
2N/A perr = 0;
2N/A }
2N/A
2N/A perr += topo_prop_set_string(strand, PGNAME(STRAND),
2N/A FM_FMRI_HC_V1_FRU_SN, TOPO_PROP_IMMUTABLE, serial, &perr);
2N/A perr += topo_prop_set_string(strand, PGNAME(STRAND),
2N/A FM_FMRI_HC_V1_FRU_PN, TOPO_PROP_IMMUTABLE, part, &perr);
2N/A perr += topo_prop_set_string(strand, PGNAME(STRAND),
2N/A FM_FMRI_HC_V1_FRU_REV, TOPO_PROP_IMMUTABLE, rev, &perr);
2N/A
2N/A if (perr != 0)
2N/A whinge(mod, NULL, "create_strand: topo_prop_set_string"
2N/A "failed\n");
2N/A
2N/A nvlist_free(fmri);
2N/A topo_mod_strfree(mod, serial);
2N/A }
2N/A
2N/A return (err == 0 && nerr == 0 ? 0 : -1);
2N/A}
2N/A
2N/Astatic int
2N/Acreate_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
2N/A nvlist_t *auth, uint16_t chip_smbiosid)
2N/A{
2N/A tnode_t *core;
2N/A int32_t coreid, cpuid;
2N/A int err, perr, nerr = 0;
2N/A nvlist_t *fmri;
2N/A char *serial = NULL;
2N/A char *part = NULL;
2N/A char *rev = NULL;
2N/A
2N/A if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
2N/A != 0) {
2N/A whinge(mod, NULL, "create_core: lookup core_id failed: %s\n",
2N/A strerror(err));
2N/A return (-1);
2N/A }
2N/A if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
2N/A if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
2N/A coreid, chip_smbiosid)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Inherit FRU from the chip node, for native, we use hc
2N/A * scheme ASRU for the core node.
2N/A */
2N/A (void) topo_node_fru_set(core, NULL, 0, &perr);
2N/A /*
2N/A * From the inherited FRU, extract the Serial
2N/A * number if SMBIOS donates and set it in the ASRU
2N/A */
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A char *val = NULL;
2N/A
2N/A if (topo_node_resource(core, &fmri, &err) != 0)
2N/A whinge(mod, NULL,
2N/A "create_core: topo_prop_get_fmri failed\n");
2N/A if (nvlist_lookup_string(fmri, FM_FMRI_HC_V1_FRU_SN,
2N/A &val) != 0)
2N/A whinge(mod, NULL, "create_core:"
2N/A "nvlist_lookup_string failed\n");
2N/A else
2N/A serial = topo_mod_strdup(mod, val);
2N/A nvlist_free(fmri);
2N/A }
2N/A if (is_xpv()) {
2N/A if (topo_node_resource(core, &fmri, &err) == -1) {
2N/A whinge(mod, &nerr, "create_core: "
2N/A "topo_node_resource failed\n");
2N/A } else {
2N/A if (FM_AWARE_SMBIOS(mod))
2N/A (void) nvlist_add_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_SN, serial);
2N/A (void) topo_node_asru_set(core, fmri, 0, &err);
2N/A nvlist_free(fmri);
2N/A }
2N/A }
2N/A if (topo_method_register(mod, core, strands_retire_methods) < 0)
2N/A whinge(mod, &nerr, "create_core: "
2N/A "topo_method_register failed\n");
2N/A
2N/A (void) topo_pgroup_create(core, &core_pgroup, &err);
2N/A nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL,
2N/A CORE_CHIP_ID, CORE_PROCNODE_ID, NULL);
2N/A
2N/A if (topo_node_range_create(mod, core, STRAND_NODE_NAME,
2N/A 0, 255) != 0)
2N/A return (-1);
2N/A }
2N/A
2N/A if (!is_xpv()) {
2N/A /*
2N/A * In native mode, we're in favor of cpu scheme ASRU for
2N/A * printing reason. More work needs to be done to support
2N/A * multi-strand cpu: the ASRU will be a list of cpuid then.
2N/A */
2N/A if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
2N/A whinge(mod, &nerr, "create_core: lookup cpuid "
2N/A "failed\n");
2N/A } else {
2N/A if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
2N/A != NULL) {
2N/A (void) topo_node_asru_set(core, fmri, 0, &err);
2N/A nvlist_free(fmri);
2N/A } else {
2N/A whinge(mod, &nerr, "create_core: "
2N/A "cpu_fmri_create() failed\n");
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A (void) topo_node_label_set(core, NULL, &perr);
2N/A
2N/A if (topo_node_resource(core, &fmri, &perr) != 0) {
2N/A whinge(mod, &nerr, "create_core: "
2N/A "topo_node_resource failed\n");
2N/A perr = 0;
2N/A }
2N/A
2N/A perr += nvlist_lookup_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_PN, &part);
2N/A perr += nvlist_lookup_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_REV, &rev);
2N/A
2N/A if (perr != 0) {
2N/A whinge(mod, NULL,
2N/A "create_core: nvlist_lookup_string failed\n");
2N/A perr = 0;
2N/A }
2N/A
2N/A perr += topo_prop_set_string(core, PGNAME(CORE),
2N/A FM_FMRI_HC_V1_FRU_SN, TOPO_PROP_IMMUTABLE, serial, &perr);
2N/A perr += topo_prop_set_string(core, PGNAME(CORE),
2N/A FM_FMRI_HC_V1_FRU_PN, TOPO_PROP_IMMUTABLE, part, &perr);
2N/A perr += topo_prop_set_string(core, PGNAME(CORE),
2N/A FM_FMRI_HC_V1_FRU_REV, TOPO_PROP_IMMUTABLE, rev, &perr);
2N/A
2N/A if (perr != 0)
2N/A whinge(mod, NULL, "create_core: topo_prop_set_string"
2N/A "failed\n");
2N/A
2N/A nvlist_free(fmri);
2N/A topo_mod_strfree(mod, serial);
2N/A }
2N/A
2N/A err = create_strand(mod, core, cpu, auth, chip_smbiosid);
2N/A
2N/A return (err == 0 && nerr == 0 ? 0 : -1);
2N/A}
2N/A
2N/Astatic int
2N/Acreate_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
2N/A topo_instance_t max, nvlist_t *cpu, nvlist_t *auth,
2N/A int mc_offchip)
2N/A{
2N/A tnode_t *chip;
2N/A nvlist_t *fmri = NULL;
2N/A int err, perr, nerr = 0;
2N/A int32_t chipid, procnodeid, procnodes_per_pkg;
2N/A const char *vendor;
2N/A int32_t family, model;
2N/A boolean_t create_mc = B_FALSE;
2N/A uint16_t smbios_id;
2N/A
2N/A /*
2N/A * /dev/fm will export the chipid based on SMBIOS' ordering
2N/A * of Type-4 structures, if SMBIOS meets FMA needs
2N/A */
2N/A err = nvlist_lookup_pairs(cpu, 0,
2N/A FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32, &chipid,
2N/A FM_PHYSCPU_INFO_NPROCNODES, DATA_TYPE_INT32, &procnodes_per_pkg,
2N/A FM_PHYSCPU_INFO_PROCNODE_ID, DATA_TYPE_INT32, &procnodeid,
2N/A FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING, &vendor,
2N/A FM_PHYSCPU_INFO_FAMILY, DATA_TYPE_INT32, &family,
2N/A FM_PHYSCPU_INFO_MODEL, DATA_TYPE_INT32, &model,
2N/A NULL);
2N/A
2N/A if (err) {
2N/A whinge(mod, NULL, "create_chip: lookup failed: %s\n",
2N/A strerror(err));
2N/A return (-1);
2N/A }
2N/A
2N/A if (chipid < min || chipid > max)
2N/A return (-1);
2N/A
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A if ((err = nvlist_lookup_uint16(cpu,
2N/A FM_PHYSCPU_INFO_SMBIOS_ID, &smbios_id)) != 0) {
2N/A whinge(mod, NULL,
2N/A "create_chip: lookup smbios_id failed"
2N/A ": enumerating x86pi & chip topology, but"
2N/A " no Chip properties from SMBIOS"
2N/A " - err msg : %s\n", strerror(err));
2N/A /*
2N/A * Lets reset the module specific
2N/A * data to NULL, overriding any
2N/A * SMBIOS capability encoded earlier.
2N/A * This will fail all subsequent
2N/A * FM_AWARE_SMBIOS checks.
2N/A */
2N/A topo_mod_setspecific(mod, NULL);
2N/A }
2N/A }
2N/A
2N/A if ((chip = topo_node_lookup(pnode, CHIP_NODE_NAME, chipid)) == NULL) {
2N/A if ((chip = create_node(mod, pnode, auth, CHIP_NODE_NAME,
2N/A chipid, smbios_id)) == NULL)
2N/A return (-1);
2N/A /*
2N/A * Do not register XML map methods if SMBIOS can provide
2N/A * serial, part, revision & label
2N/A */
2N/A if (!FM_AWARE_SMBIOS(mod)) {
2N/A if (topo_method_register(mod, chip, chip_methods) < 0)
2N/A whinge(mod, &nerr, "create_chip: "
2N/A "topo_method_register failed\n");
2N/A }
2N/A
2N/A (void) topo_pgroup_create(chip, &chip_pgroup, &err);
2N/A nerr -= add_nvlist_strprop(mod, chip, cpu, PGNAME(CHIP),
2N/A CHIP_VENDOR_ID, NULL);
2N/A nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP),
2N/A NULL, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL);
2N/A
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A int fru = 0;
2N/A char *serial = NULL;
2N/A char *part = NULL;
2N/A char *rev = NULL;
2N/A char *label;
2N/A
2N/A fru = chip_fru_smbios_get(mod, smbios_id);
2N/A /*
2N/A * Chip is not a FRU, set the FRU fmri of parent node
2N/A */
2N/A if (topo_node_resource(chip, &fmri, &perr) != 0)
2N/A whinge(mod, &nerr, "create_chip: "
2N/A "topo_node_resource failed\n");
2N/A if (!fru) {
2N/A (void) topo_node_fru_set(chip, NULL, 0, &perr);
2N/A label = NULL;
2N/A } else {
2N/A label = (char *)chip_label_smbios_get(mod,
2N/A pnode, smbios_id, NULL);
2N/A
2N/A if (topo_node_fru_set(chip, fmri, 0, &perr)
2N/A != 0) {
2N/A whinge(mod, NULL, "create_chip: "
2N/A "topo_node_fru_set failed\n");
2N/A perr = 0;
2N/A }
2N/A }
2N/A
2N/A perr += nvlist_lookup_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_SN, &serial);
2N/A perr += nvlist_lookup_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_PN, &part);
2N/A perr += nvlist_lookup_string(fmri,
2N/A FM_FMRI_HC_V1_FRU_REV, &rev);
2N/A
2N/A if (perr != 0) {
2N/A whinge(mod, NULL,
2N/A "create_chip: nvlist_lookup_string"
2N/A "failed\n");
2N/A perr = 0;
2N/A }
2N/A
2N/A perr += topo_prop_set_string(chip, PGNAME(CHIP),
2N/A FM_FMRI_HC_V1_FRU_SN, TOPO_PROP_IMMUTABLE,
2N/A serial, &perr);
2N/A perr += topo_prop_set_string(chip, PGNAME(CHIP),
2N/A FM_FMRI_HC_V1_FRU_PN, TOPO_PROP_IMMUTABLE,
2N/A part, &perr);
2N/A perr += topo_prop_set_string(chip, PGNAME(CHIP),
2N/A FM_FMRI_HC_V1_FRU_REV, TOPO_PROP_IMMUTABLE,
2N/A rev, &perr);
2N/A
2N/A if (perr != 0)
2N/A whinge(mod, NULL,
2N/A "create_chip: topo_prop_set_string"
2N/A "failed\n");
2N/A
2N/A nvlist_free(fmri);
2N/A
2N/A if (topo_node_label_set(chip, label, &perr)
2N/A == -1) {
2N/A whinge(mod, NULL, "create_chip: "
2N/A "topo_node_label_set failed\n");
2N/A }
2N/A topo_mod_strfree(mod, label);
2N/A
2N/A } else {
2N/A if (topo_node_resource(chip, &fmri, &err) == -1) {
2N/A whinge(mod, &nerr, "create_chip: "
2N/A "topo_node_resource failed\n");
2N/A } else {
2N/A (void) topo_node_fru_set(chip, fmri, 0, &perr);
2N/A nvlist_free(fmri);
2N/A }
2N/A }
2N/A
2N/A if (topo_method_register(mod, chip, strands_retire_methods) < 0)
2N/A whinge(mod, &nerr, "create_chip: "
2N/A "topo_method_register failed\n");
2N/A
2N/A if (topo_node_range_create(mod, chip, CORE_NODE_NAME, 0, 255))
2N/A return (-1);
2N/A
2N/A if (strcmp(vendor, "AuthenticAMD") == 0) {
2N/A if (topo_node_range_create(mod, chip, MCT_NODE_NAME,
2N/A 0, 255))
2N/A return (-1);
2N/A }
2N/A
2N/A create_mc = B_TRUE;
2N/A }
2N/A
2N/A if (FM_AWARE_SMBIOS(mod)) {
2N/A int status = 0;
2N/A /*
2N/A * STATUS
2N/A * CPU Socket Populated
2N/A * CPU Socket Unpopulated
2N/A * Populated : Enabled
2N/A * Populated : Disabled by BIOS (Setup)
2N/A * Populated : Disabled by BIOS (Error)
2N/A * Populated : Idle
2N/A *
2N/A * Enumerate core & strand only for Populated : Enabled
2N/A * Enumerate Off-Chip Memory Controller only for
2N/A * Populated : Enabled
2N/A */
2N/A
2N/A status = chip_status_smbios_get(mod, (id_t)smbios_id);
2N/A if (!status) {
2N/A whinge(mod, NULL, "create_chip: "
2N/A "CPU Socket is not populated or is disabled\n");
2N/A return (0);
2N/A }
2N/A }
2N/A
2N/A err = create_core(mod, chip, cpu, auth, smbios_id);
2N/A
2N/A /*
2N/A * Create memory-controller node under a chip for architectures
2N/A * that may have on-chip memory-controller(s).
2N/A * If SMBIOS meets FMA needs, when Multi-Chip-Module is
2N/A * addressed, mc instances should be derived from SMBIOS
2N/A */
2N/A if (strcmp(vendor, "AuthenticAMD") == 0) {
2N/A amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth,
2N/A procnodeid, procnodes_per_pkg, family, model, &nerr);
2N/A } else if (create_mc && !mc_offchip)
2N/A onchip_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth);
2N/A
2N/A return (err == 0 && nerr == 0 ? 0 : -1);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Astatic int
2N/Acreate_chips(topo_mod_t *mod, tnode_t *pnode, const char *name,
2N/A topo_instance_t min, topo_instance_t max, void *arg, nvlist_t *auth,
2N/A int mc_offchip)
2N/A{
2N/A fmd_agent_hdl_t *hdl;
2N/A nvlist_t **cpus;
2N/A int nerr = 0;
2N/A uint_t i, ncpu;
2N/A
2N/A if (strcmp(name, CHIP_NODE_NAME) != 0)
2N/A return (0);
2N/A
2N/A if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL)
2N/A return (-1);
2N/A if (fmd_agent_physcpu_info(hdl, &cpus, &ncpu) != 0) {
2N/A whinge(mod, NULL, "create_chip: fmd_agent_physcpu_info "
2N/A "failed: %s\n", fmd_agent_errmsg(hdl));
2N/A fmd_agent_close(hdl);
2N/A return (-1);
2N/A }
2N/A fmd_agent_close(hdl);
2N/A
2N/A for (i = 0; i < ncpu; i++) {
2N/A nerr -= create_chip(mod, pnode, min, max, cpus[i], auth,
2N/A mc_offchip);
2N/A nvlist_free(cpus[i]);
2N/A }
2N/A umem_free(cpus, sizeof (nvlist_t *) * ncpu);
2N/A
2N/A if (nerr == 0) {
2N/A return (0);
2N/A } else {
2N/A (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
2N/A return (-1);
2N/A }
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Astatic int
2N/Achip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
2N/A topo_instance_t min, topo_instance_t max, void *arg, void *smbios_enabled)
2N/A{
2N/A int rv = 0;
2N/A nvlist_t *auth = NULL;
2N/A int offchip_mc;
2N/A char buf[BUFSIZ];
2N/A const char *dom0 = "control_d";
2N/A
2N/A /*
2N/A * Create nothing if we're running in domU.
2N/A */
2N/A if (sysinfo(SI_PLATFORM, buf, sizeof (buf)) == -1)
2N/A return (-1);
2N/A
2N/A if (strncmp(buf, "i86pc", sizeof (buf)) != 0 &&
2N/A strncmp(buf, "i86xpv", sizeof (buf)) != 0)
2N/A return (0);
2N/A
2N/A if (strncmp(buf, "i86xpv", sizeof (buf)) == 0) {
2N/A int fd = open("/dev/xen/domcaps", O_RDONLY);
2N/A
2N/A if (fd != -1) {
2N/A if (read(fd, buf, sizeof (buf)) <= 0 ||
2N/A strncmp(buf, dom0, strlen(dom0)) != 0) {
2N/A (void) close(fd);
2N/A return (0);
2N/A }
2N/A (void) close(fd);
2N/A }
2N/A }
2N/A
2N/A /* Initailize SMBIOS struct ID counts */
2N/A ncpu_ids = 0;
2N/A bb_count = 0;
2N/A ndimm_ids = 0;
2N/A nmct_ids = 0;
2N/A
2N/A /*
2N/A * Set Chip Enumerator Module's private data with the value passed by
2N/A * x86pi Enumerator, defining SMBIOS capabilities
2N/A */
2N/A topo_mod_setspecific(mod, smbios_enabled);
2N/A
2N/A if (FM_AWARE_SMBIOS(mod))
2N/A if (init_chip_smbios(mod) != 0) {
2N/A whinge(mod, NULL,
2N/A "init_chip_smbios() failed, "
2N/A " enumerating x86pi & chip topology, but no"
2N/A " CPU & Memory properties will be"
2N/A " derived from SMBIOS\n");
2N/A /*
2N/A * Lets reset the module specific
2N/A * data to NULL, overriding any
2N/A * SMBIOS capability encoded earlier.
2N/A * This will fail all subsequent
2N/A * FM_AWARE_SMBIOS checks.
2N/A */
2N/A topo_mod_setspecific(mod, NULL);
2N/A }
2N/A
2N/A auth = topo_mod_auth(mod, pnode);
2N/A
2N/A offchip_mc = mc_offchip_open();
2N/A if (strcmp(name, CHIP_NODE_NAME) == 0)
2N/A rv = create_chips(mod, pnode, name, min, max, NULL, auth,
2N/A offchip_mc);
2N/A
2N/A if (offchip_mc)
2N/A (void) mc_offchip_create(mod, pnode, "memory-controller", auth);
2N/A
2N/A nvlist_free(auth);
2N/A
2N/A return (rv);
2N/A}