Home | History | Annotate | Download | only in cpumem-diagnosis
      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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 
     27 /*
     28  * Support routines for managing per-CPU state.
     29  */
     30 
     31 #include <cmd_cpu.h>
     32 #include <cmd_ecache.h>
     33 #include <cmd_mem.h>
     34 #include <cmd.h>
     35 
     36 #include <stdio.h>
     37 #include <string.h>
     38 #include <strings.h>
     39 #include <errno.h>
     40 #include <kstat.h>
     41 #include <fm/fmd_api.h>
     42 #include <sys/async.h>
     43 #include <sys/fm/protocol.h>
     44 #include <sys/fm/cpu/UltraSPARC-III.h>
     45 #include <sys/cheetahregs.h>
     46 
     47 /*
     48  * The unused argument 'clcode' is needed for our sun4v sibling.
     49  */
     50 
     51 /*ARGSUSED*/
     52 int
     53 cmd_xr_fill(fmd_hdl_t *hdl, nvlist_t *nvl, cmd_xr_t *xr, cmd_errcl_t clcode)
     54 {
     55 	if (nvlist_lookup_uint16(nvl, FM_EREPORT_PAYLOAD_NAME_SYND,
     56 	    &xr->xr_synd) != 0)
     57 		return (-1);
     58 	if (nvlist_lookup_uint8(nvl, FM_EREPORT_PAYLOAD_NAME_SYND_STATUS,
     59 	    &xr->xr_synd_status) != 0)
     60 		return (-1);
     61 	if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_NAME_AFAR,
     62 	    &xr->xr_afar) != 0)
     63 		return (-1);
     64 	if (nvlist_lookup_uint8(nvl, FM_EREPORT_PAYLOAD_NAME_AFAR_STATUS,
     65 	    &xr->xr_afar_status) != 0)
     66 		return (-1);
     67 	return (0);
     68 }
     69 
     70 /*
     71  * Search for the entry that matches the ena and the AFAR
     72  * if we have a valid AFAR, otherwise just match the ENA
     73  */
     74 cmd_xxcu_trw_t *
     75 cmd_trw_lookup(uint64_t ena, uint8_t afar_status, uint64_t afar)
     76 {
     77 	int i;
     78 
     79 	if (afar_status == AFLT_STAT_VALID) {
     80 		for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
     81 			if (cmd.cmd_xxcu_trw[i].trw_ena == ena &&
     82 			    cmd.cmd_xxcu_trw[i].trw_afar == afar)
     83 				return (&cmd.cmd_xxcu_trw[i]);
     84 		}
     85 	} else  {
     86 		for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
     87 		if (cmd.cmd_xxcu_trw[i].trw_ena == ena)
     88 			return (&cmd.cmd_xxcu_trw[i]);
     89 		}
     90 	}
     91 	return (NULL);
     92 }
     93 
     94 /*ARGSUSED*/
     95 cmd_errcl_t
     96 cmd_train_match(cmd_errcl_t trw_mask, cmd_errcl_t resolved_err)
     97 {
     98 	return (cmd_xxcu_train_match(trw_mask));
     99 }
    100 
    101 /*ARGSUSED*/
    102 int
    103 cmd_afar_status_check(uint8_t afar_status, cmd_errcl_t clcode)
    104 {
    105 	if (afar_status == AFLT_STAT_VALID)
    106 		return (0);
    107 	return (-1);
    108 }
    109 
    110 const errdata_t l3errdata =
    111 	{ &cmd.cmd_l3data_serd, "l3cachedata", CMD_PTR_CPU_L3DATA  };
    112 const errdata_t l2errdata =
    113 	{ &cmd.cmd_l2data_serd, "l2cachedata", CMD_PTR_CPU_L2DATA };
    114 
    115 void
    116 cmd_fill_errdata(cmd_errcl_t clcode, cmd_cpu_t *cpu, cmd_case_t **cc,
    117     const errdata_t **ed)
    118 {
    119 	if (CMD_ERRCL_ISL2XXCU(clcode)) {
    120 		*ed = &l2errdata;
    121 		*cc = &cpu->cpu_l2data;
    122 	} else {
    123 		*ed = &l3errdata;
    124 		*cc = &cpu->cpu_l3data;
    125 	}
    126 }
    127 
    128 /*ARGSUSED*/
    129 int
    130 cmd_cpu_synd_check(uint16_t synd, cmd_errcl_t clcode)
    131 {
    132 	if (synd == CH_POISON_SYND_FROM_XXU_WRITE ||
    133 	    synd == CH_POISON_SYND_FROM_XXU_WRMERGE ||
    134 	    synd == CH_POISON_SYND_FROM_DSTAT23)
    135 		return (-1);
    136 	else
    137 		return (0);
    138 }
    139 /*ARGSUSED*/
    140 int
    141 cmd_afar_valid(fmd_hdl_t *hdl, nvlist_t *nvl, cmd_errcl_t clcode,
    142     uint64_t *afar)
    143 {
    144 	uint8_t afar_status;
    145 
    146 	if (nvlist_lookup_uint8(nvl,
    147 	    FM_EREPORT_PAYLOAD_NAME_AFAR_STATUS, &afar_status) == 0) {
    148 		if (afar_status == AFLT_STAT_VALID) {
    149 			(void) nvlist_lookup_uint64(nvl,
    150 			    FM_EREPORT_PAYLOAD_NAME_AFAR, afar);
    151 			return (0);
    152 		} else
    153 			return (-1);
    154 	} else
    155 		return (-1);
    156 }
    157 
    158 char *
    159 cmd_cpu_getfrustr_by_id(fmd_hdl_t *hdl, uint32_t cpuid)
    160 {
    161 	kstat_named_t *kn;
    162 	kstat_ctl_t *kc;
    163 	kstat_t *ksp;
    164 	int i;
    165 
    166 	if ((kc = kstat_open()) == NULL)
    167 		return (NULL); /* errno is set for us */
    168 
    169 	if ((ksp = kstat_lookup(kc, "cpu_info", cpuid, NULL)) == NULL ||
    170 	    kstat_read(kc, ksp, NULL) == -1) {
    171 		int oserr = errno;
    172 		(void) kstat_close(kc);
    173 		(void) cmd_set_errno(oserr);
    174 		return (NULL);
    175 	}
    176 
    177 	for (kn = ksp->ks_data, i = 0; i < ksp->ks_ndata; i++, kn++) {
    178 		if (strcmp(kn->name, "cpu_fru") == 0) {
    179 			char *str = fmd_hdl_strdup(hdl,
    180 			    KSTAT_NAMED_STR_PTR(kn), FMD_SLEEP);
    181 			(void) kstat_close(kc);
    182 			return (str);
    183 		}
    184 	}
    185 
    186 	(void) kstat_close(kc);
    187 	(void) cmd_set_errno(ENOENT);
    188 	return (NULL);
    189 }
    190 
    191 char *
    192 cmd_cpu_getfrustr(fmd_hdl_t *hdl, cmd_cpu_t *cp)
    193 {
    194 	return (cmd_cpu_getfrustr_by_id(hdl, cp->cpu_cpuid));
    195 }
    196 
    197 /*ARGSUSED*/
    198 char *
    199 cmd_cpu_getpartstr(fmd_hdl_t *hdl, cmd_cpu_t *cp) {
    200 	return (NULL);
    201 }
    202 
    203 /*ARGSUSED*/
    204 char *
    205 cmd_cpu_getserialstr(fmd_hdl_t *hdl, cmd_cpu_t *cp) {
    206 	return (NULL);
    207 }
    208 
    209 /*ARGSUSED*/
    210 nvlist_t *
    211 cmd_cpu_mkfru(fmd_hdl_t *hdl, char *frustr, char *serialstr, char *partstr)
    212 {
    213 	char *comp;
    214 	nvlist_t *fru, *hcelem;
    215 
    216 	if (strncmp(frustr, CPU_FRU_FMRI, sizeof (CPU_FRU_FMRI) - 1) != 0)
    217 		return (NULL);
    218 
    219 	comp = frustr + sizeof (CPU_FRU_FMRI) - 1;
    220 
    221 	if (nvlist_alloc(&hcelem, NV_UNIQUE_NAME, 0) != 0)
    222 		return (NULL);
    223 
    224 	if (nvlist_add_string(hcelem, FM_FMRI_HC_NAME,
    225 	    FM_FMRI_LEGACY_HC) != 0 ||
    226 	    nvlist_add_string(hcelem, FM_FMRI_HC_ID, comp) != 0) {
    227 		nvlist_free(hcelem);
    228 		return (NULL);
    229 	}
    230 
    231 	if (nvlist_alloc(&fru, NV_UNIQUE_NAME, 0) != 0) {
    232 		nvlist_free(hcelem);
    233 		return (NULL);
    234 	}
    235 
    236 	if (nvlist_add_uint8(fru, FM_VERSION, FM_HC_SCHEME_VERSION) != 0 ||
    237 	    nvlist_add_string(fru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC) != 0 ||
    238 	    (partstr != NULL &&
    239 	    nvlist_add_string(fru, FM_FMRI_HC_PART, partstr) != 0) ||
    240 	    (serialstr != NULL &&
    241 	    nvlist_add_string(fru, FM_FMRI_HC_SERIAL_ID,
    242 	    serialstr) != 0) ||
    243 	    nvlist_add_string(fru, FM_FMRI_HC_ROOT, "") != 0 ||
    244 	    nvlist_add_uint32(fru, FM_FMRI_HC_LIST_SZ, 1) != 0 ||
    245 	    nvlist_add_nvlist_array(fru, FM_FMRI_HC_LIST, &hcelem, 1) != 0) {
    246 		nvlist_free(hcelem);
    247 		nvlist_free(fru);
    248 		return (NULL);
    249 	}
    250 
    251 	nvlist_free(hcelem);
    252 	return (fru);
    253 }
    254 
    255 nvlist_t *
    256 cmd_nvl_create_fault(fmd_hdl_t *hdl, const char *class, uint8_t cert,
    257     nvlist_t *asru, nvlist_t *fru, nvlist_t *rsrc)
    258 {
    259 	(void) nvlist_add_nvlist(fru, FM_FMRI_AUTHORITY,
    260 	    cmd.cmd_auth);
    261 	return (fmd_nvl_create_fault(hdl, class, cert, asru, fru, rsrc));
    262 }
    263