chip.c revision 8a40a695ee676a322b094e9afe5375567bfb51e3
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <alloca.h>
#include <kstat.h>
#include <fcntl.h>
#include <errno.h>
#include <libnvpair.h>
#include <sys/processor.h>
#include <sys/systeminfo.h>
#include <fm/topo_mod.h>
#include "chip.h"
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#define MAX_DIMMNUM 7
#define MAX_CSNUM 7
/*
* Enumerates the processing chips, or sockets, (as distinct from cores) in a
* system. For each chip found, the necessary nodes (one or more cores, and
* possibly a memory controller) are constructed underneath.
*/
topo_instance_t, void *);
const topo_modinfo_t chip_info =
const topo_method_t rank_methods[] = {
{ NULL }
};
static const struct debugopt {
const char *optname;
int optval;
} debugopts[] = {
{ "err", TOPO_DBG_ERR },
{ "mod", TOPO_DBG_MOD },
{ "log", TOPO_DBG_LOG },
{ "walk", TOPO_DBG_WALK },
{ "tree", TOPO_DBG_TREE },
{ "all", TOPO_DBG_ALL }
};
static void
{
char buf[160];
++*nerr;
}
int
{
int i;
i++) {
break; /* handle a single option only */
}
}
}
}
}
return (-1); /* mod errno set */
}
return (0);
}
void
{
}
static int
{
int err;
kstat_named_t *k;
return (0);
return (-1);
}
static int
{
int err;
kstat_named_t *k;
return (0);
return (-1);
}
static int
{
int err;
return (-1);
}
}
static nvlist_t *
{
int err;
return (NULL);
if (s != NULL)
if (err != 0) {
return (NULL);
}
return (asru);
}
static nvlist_t *
{
return (NULL);
return (NULL);
}
return (asru);
}
static int
{
kstat_named_t *k;
chip->chip_ncpustats) < 0)
return (-1);
for (i = 0; i <= chip->chip_ncpustats; i++) {
continue;
/*
* The chip_id in the cpu_info kstat numbers the individual
* chips from 0 to #chips - 1.
*/
== NULL) {
"kstats failed\n");
continue;
}
continue; /* not an error */
/*
* The clog_id in the cpu_info kstat numbers the processor
* cores of a single chip from 0 to #chips - 1.
*/
== NULL) {
"kstats failed\n");
continue;
}
continue;
}
/*
* The core_id in the cpu_info kstat corresponds to the
* processor id used in psradm etc - ie cpuid as used
* in a cpu scheme fmri. I'm not making this up!
*/
== NULL) {
"kstats failed\n");
continue;
}
continue;
}
} else {
"failed\n");
}
}
return (nerr == 0 ? 0 : -1);
}
static int
{
int err = 0;
switch (nvpair_type(nvp)) {
case DATA_TYPE_BOOLEAN_VALUE: {
}
return (0);
}
case DATA_TYPE_UINT64: {
}
return (0);
}
case DATA_TYPE_STRING: {
char *str;
return (0);
}
default:
"'%s' in property group %s of %s node\n",
return (1);
}
}
static int
{
char *socket;
int i, nchan;
/*
* We will enumerate the number of channels present even if only
* channel A is in use (i.e., running in 64-bit mode). Only
* the socket 754 package has a single channel.
*/
return (-1);
nchan = 1;
else
nchan = 2;
return (-1);
for (i = 0; i < nchan; i++) {
"failed\n");
continue;
}
"failed\n");
continue;
}
}
return (nerr == 0 ? 0 : -1);
}
static int
{
return (-1);
if (ncs == 0)
return (0); /* no chip-selects configured on this node */
return (-1);
for (i = 0; i < ncs; i++) {
"missing\n");
continue;
}
continue;
}
continue;
}
}
}
return (nerr == 0 ? 0 : -1);
}
/*
* Registered method for asru computation for rank nodes. The 'node'
* argument identifies the node for which we seek an asru. The 'in'
* argument is used to select which asru we will return, as follows:
*
* - the node name must be "dimm" or "rank"
* - if 'in' is NULL then return any statically defined asru for this node
* - if 'in' is an "hc" scheme fmri then we construct a "mem" scheme asru
* with unum being the hc path to the dimm or rank (this method is called
* as part of dynamic asru computation for rank nodes only, but dimm_create
* also calls it directly to construct a "mem" scheme asru for a dimm node)
* - if 'in' in addition includes an hc-specific member which specifies
* asru-physaddr or asru-offset then these are includes in the "mem" scheme
* asru as additional membersl physaddr and offset
*/
/*ARGSUSED*/
static int
{
int incl_pa = 0, incl_offset = 0;
int err;
return (0);
else
} else {
}
&pa) == 0)
incl_pa = 1;
&offset) == 0)
incl_offset = 1;
}
/* use 'in' to obtain resource path; could use node resource */
}
if (incl_pa)
if (incl_offset)
if (err != 0) {
}
return (0);
}
static int
{
char **csnamearr;
int nerr = 0;
int err;
int i;
return (nerr);
}
"failed\n");
return (nerr);
}
return (nerr);
}
} else {
return (nerr);
}
for (i = 0; i < ncs; i++) {
continue;
}
"failed\n");
continue;
}
/*
* If a rank is faulted the asru is the associated
* chip-select, but if a page within a rank is faulted
* the asru is just that page. Hence the dual preconstructed
* and computed ASRU.
*/
TOPO_ASRU_COMPUTE, &err);
"topo_method_register failed");
}
return (nerr);
}
static int
{
return (-1);
}
if (ndimm == 0)
return (0); /* no dimms present on this node */
return (-1);
}
for (i = 0; i < ndimm; i++) {
"missing\n");
continue;
}
continue;
}
"failed\n");
continue;
}
/*
* The asru is static but we prefer to publish it in the
* "mem" scheme so call the compute method directly to
* perform the conversion.
*/
} else {
"failed\n");
continue;
}
continue; /* used in rank_create() */
}
}
return (nerr == 0 ? 0 : -1);
}
static nvlist_t *
{
char path[64];
if (fd == -1) {
/*
* Some v20z and v40z systems may have had the 3rd-party
* link. So try again via /devices.
*/
MC_AMD_DEV_OFFSET + id);
}
if (fd == -1) {
return (NULL);
}
return (NULL);
}
return (NULL);
} else if (ver != MC_NVLIST_VERS1) {
return (NULL);
}
}
static int
{
int i;
return (-1);
}
return (-1);
}
/*
* Gather and create memory controller topology
*/
return (-1);
}
/*
* Add memory controller properties
*/
continue;
continue;
} else {
rc = -1;
}
}
rc = -1;
/*
* Free the fmris for the chip-selects allocated in cs_create
*/
for (i = 0; i < MC_CHIP_NCS; i++) {
nvlist_free(cs_fmri[i]);
}
}
return (rc);
}
static int
{
int i, nerr = 0;
break;
continue;
}
for (i = 0; i <= chip->chip_ncpustats; i++) {
kstat_named_t *k;
continue;
"via kstats failed\n");
continue;
}
continue;
continue;
continue;
}
"failed for chipid %d\n", chipid);
continue;
}
nerr++; /* have whinged elsewhere */
}
if (nerr == 0) {
return (0);
} else {
return (-1);
}
}
static int
{
return (0);
}