1962Stsien /*
2962Stsien * CDDL HEADER START
3962Stsien *
4962Stsien * The contents of this file are subject to the terms of the
52828Sjc25722 * Common Development and Distribution License (the "License").
62828Sjc25722 * You may not use this file except in compliance with the License.
7962Stsien *
8962Stsien * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9962Stsien * or http://www.opensolaris.org/os/licensing.
10962Stsien * See the License for the specific language governing permissions
11962Stsien * and limitations under the License.
12962Stsien *
13962Stsien * When distributing Covered Code, include this CDDL HEADER in each
14962Stsien * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15962Stsien * If applicable, add the following below this CDDL HEADER, with the
16962Stsien * fields enclosed by brackets "[]" replaced with your own identifying
17962Stsien * information: Portions Copyright [yyyy] [name of copyright owner]
18962Stsien *
19962Stsien * CDDL HEADER END
20962Stsien */
21962Stsien /*
226369Std122701 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23962Stsien * Use is subject to license terms.
24962Stsien */
25962Stsien
26962Stsien
27962Stsien /*
28962Stsien * Support routines for managing per-CPU state.
29962Stsien */
30962Stsien
31962Stsien #include <cmd_cpu.h>
32962Stsien #include <cmd_ecache.h>
33962Stsien #include <cmd_mem.h>
34962Stsien #include <cmd.h>
35962Stsien
36962Stsien #include <stdio.h>
37962Stsien #include <string.h>
38962Stsien #include <strings.h>
39962Stsien #include <errno.h>
40962Stsien #include <kstat.h>
41962Stsien #include <fm/fmd_api.h>
42962Stsien #include <sys/async.h>
43962Stsien #include <sys/fm/protocol.h>
44962Stsien #include <sys/fm/cpu/UltraSPARC-III.h>
45962Stsien #include <sys/cheetahregs.h>
46962Stsien
47962Stsien /*
48962Stsien * The unused argument 'clcode' is needed for our sun4v sibling.
49962Stsien */
50962Stsien
51962Stsien /*ARGSUSED*/
52962Stsien int
cmd_xr_fill(fmd_hdl_t * hdl,nvlist_t * nvl,cmd_xr_t * xr,cmd_errcl_t clcode)53962Stsien cmd_xr_fill(fmd_hdl_t *hdl, nvlist_t *nvl, cmd_xr_t *xr, cmd_errcl_t clcode)
54962Stsien {
55962Stsien if (nvlist_lookup_uint16(nvl, FM_EREPORT_PAYLOAD_NAME_SYND,
56962Stsien &xr->xr_synd) != 0)
57962Stsien return (-1);
58962Stsien if (nvlist_lookup_uint8(nvl, FM_EREPORT_PAYLOAD_NAME_SYND_STATUS,
59962Stsien &xr->xr_synd_status) != 0)
60962Stsien return (-1);
61962Stsien if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_NAME_AFAR,
62962Stsien &xr->xr_afar) != 0)
63962Stsien return (-1);
64962Stsien if (nvlist_lookup_uint8(nvl, FM_EREPORT_PAYLOAD_NAME_AFAR_STATUS,
65962Stsien &xr->xr_afar_status) != 0)
66962Stsien return (-1);
67962Stsien return (0);
68962Stsien }
69962Stsien
706369Std122701 /*
716369Std122701 * Search for the entry that matches the ena and the AFAR
726369Std122701 * if we have a valid AFAR, otherwise just match the ENA
736369Std122701 */
746369Std122701 cmd_xxcu_trw_t *
cmd_trw_lookup(uint64_t ena,uint8_t afar_status,uint64_t afar)756369Std122701 cmd_trw_lookup(uint64_t ena, uint8_t afar_status, uint64_t afar)
766369Std122701 {
776369Std122701 int i;
786369Std122701
796369Std122701 if (afar_status == AFLT_STAT_VALID) {
806369Std122701 for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
816369Std122701 if (cmd.cmd_xxcu_trw[i].trw_ena == ena &&
826369Std122701 cmd.cmd_xxcu_trw[i].trw_afar == afar)
836369Std122701 return (&cmd.cmd_xxcu_trw[i]);
846369Std122701 }
856369Std122701 } else {
866369Std122701 for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
876369Std122701 if (cmd.cmd_xxcu_trw[i].trw_ena == ena)
886369Std122701 return (&cmd.cmd_xxcu_trw[i]);
896369Std122701 }
906369Std122701 }
916369Std122701 return (NULL);
926369Std122701 }
936369Std122701
946369Std122701 /*ARGSUSED*/
956369Std122701 cmd_errcl_t
cmd_train_match(cmd_errcl_t trw_mask,cmd_errcl_t resolved_err)966369Std122701 cmd_train_match(cmd_errcl_t trw_mask, cmd_errcl_t resolved_err)
976369Std122701 {
986369Std122701 return (cmd_xxcu_train_match(trw_mask));
996369Std122701 }
1006369Std122701
1016369Std122701 /*ARGSUSED*/
102962Stsien int
cmd_afar_status_check(uint8_t afar_status,cmd_errcl_t clcode)1036369Std122701 cmd_afar_status_check(uint8_t afar_status, cmd_errcl_t clcode)
1046369Std122701 {
1056369Std122701 if (afar_status == AFLT_STAT_VALID)
1066369Std122701 return (0);
1076369Std122701 return (-1);
1086369Std122701 }
1096369Std122701
1106369Std122701 const errdata_t l3errdata =
1116369Std122701 { &cmd.cmd_l3data_serd, "l3cachedata", CMD_PTR_CPU_L3DATA };
1126369Std122701 const errdata_t l2errdata =
1136369Std122701 { &cmd.cmd_l2data_serd, "l2cachedata", CMD_PTR_CPU_L2DATA };
1146369Std122701
1156369Std122701 void
cmd_fill_errdata(cmd_errcl_t clcode,cmd_cpu_t * cpu,cmd_case_t ** cc,const errdata_t ** ed)1166369Std122701 cmd_fill_errdata(cmd_errcl_t clcode, cmd_cpu_t *cpu, cmd_case_t **cc,
1176369Std122701 const errdata_t **ed)
1186369Std122701 {
1196369Std122701 if (CMD_ERRCL_ISL2XXCU(clcode)) {
1206369Std122701 *ed = &l2errdata;
1216369Std122701 *cc = &cpu->cpu_l2data;
1226369Std122701 } else {
1236369Std122701 *ed = &l3errdata;
1246369Std122701 *cc = &cpu->cpu_l3data;
1256369Std122701 }
1266369Std122701 }
1276369Std122701
1286369Std122701 /*ARGSUSED*/
1296369Std122701 int
cmd_cpu_synd_check(uint16_t synd,cmd_errcl_t clcode)1306369Std122701 cmd_cpu_synd_check(uint16_t synd, cmd_errcl_t clcode)
131962Stsien {
132962Stsien if (synd == CH_POISON_SYND_FROM_XXU_WRITE ||
133962Stsien synd == CH_POISON_SYND_FROM_XXU_WRMERGE ||
134962Stsien synd == CH_POISON_SYND_FROM_DSTAT23)
135962Stsien return (-1);
136962Stsien else
137962Stsien return (0);
138962Stsien }
1392833Sjc25722 /*ARGSUSED*/
1402828Sjc25722 int
cmd_afar_valid(fmd_hdl_t * hdl,nvlist_t * nvl,cmd_errcl_t clcode,uint64_t * afar)1412828Sjc25722 cmd_afar_valid(fmd_hdl_t *hdl, nvlist_t *nvl, cmd_errcl_t clcode,
1422828Sjc25722 uint64_t *afar)
1432828Sjc25722 {
1442828Sjc25722 uint8_t afar_status;
1452828Sjc25722
1462828Sjc25722 if (nvlist_lookup_uint8(nvl,
1472828Sjc25722 FM_EREPORT_PAYLOAD_NAME_AFAR_STATUS, &afar_status) == 0) {
1482828Sjc25722 if (afar_status == AFLT_STAT_VALID) {
1492828Sjc25722 (void) nvlist_lookup_uint64(nvl,
1502828Sjc25722 FM_EREPORT_PAYLOAD_NAME_AFAR, afar);
1512828Sjc25722 return (0);
1522828Sjc25722 } else
1532828Sjc25722 return (-1);
1543325Ssd77468 } else
1553325Ssd77468 return (-1);
1563325Ssd77468 }
1573325Ssd77468
1583325Ssd77468 char *
cmd_cpu_getfrustr_by_id(fmd_hdl_t * hdl,uint32_t cpuid)1593325Ssd77468 cmd_cpu_getfrustr_by_id(fmd_hdl_t *hdl, uint32_t cpuid)
1603325Ssd77468 {
1613325Ssd77468 kstat_named_t *kn;
1623325Ssd77468 kstat_ctl_t *kc;
1633325Ssd77468 kstat_t *ksp;
1643325Ssd77468 int i;
1653325Ssd77468
1663325Ssd77468 if ((kc = kstat_open()) == NULL)
1673325Ssd77468 return (NULL); /* errno is set for us */
1683325Ssd77468
1693325Ssd77468 if ((ksp = kstat_lookup(kc, "cpu_info", cpuid, NULL)) == NULL ||
1703325Ssd77468 kstat_read(kc, ksp, NULL) == -1) {
1713325Ssd77468 int oserr = errno;
1723325Ssd77468 (void) kstat_close(kc);
1733325Ssd77468 (void) cmd_set_errno(oserr);
1743325Ssd77468 return (NULL);
1752828Sjc25722 }
1763325Ssd77468
1773325Ssd77468 for (kn = ksp->ks_data, i = 0; i < ksp->ks_ndata; i++, kn++) {
1783325Ssd77468 if (strcmp(kn->name, "cpu_fru") == 0) {
1793325Ssd77468 char *str = fmd_hdl_strdup(hdl,
1803325Ssd77468 KSTAT_NAMED_STR_PTR(kn), FMD_SLEEP);
1813325Ssd77468 (void) kstat_close(kc);
1823325Ssd77468 return (str);
1833325Ssd77468 }
1843325Ssd77468 }
1853325Ssd77468
1863325Ssd77468 (void) kstat_close(kc);
1873325Ssd77468 (void) cmd_set_errno(ENOENT);
1883325Ssd77468 return (NULL);
1892828Sjc25722 }
1903325Ssd77468
1913325Ssd77468 char *
cmd_cpu_getfrustr(fmd_hdl_t * hdl,cmd_cpu_t * cp)1923325Ssd77468 cmd_cpu_getfrustr(fmd_hdl_t *hdl, cmd_cpu_t *cp)
1933325Ssd77468 {
1943325Ssd77468 return (cmd_cpu_getfrustr_by_id(hdl, cp->cpu_cpuid));
1953325Ssd77468 }
1963325Ssd77468
1973325Ssd77468 /*ARGSUSED*/
1983325Ssd77468 char *
cmd_cpu_getpartstr(fmd_hdl_t * hdl,cmd_cpu_t * cp)1993325Ssd77468 cmd_cpu_getpartstr(fmd_hdl_t *hdl, cmd_cpu_t *cp) {
2003325Ssd77468 return (NULL);
2013325Ssd77468 }
2023325Ssd77468
2033325Ssd77468 /*ARGSUSED*/
2043325Ssd77468 char *
cmd_cpu_getserialstr(fmd_hdl_t * hdl,cmd_cpu_t * cp)2053325Ssd77468 cmd_cpu_getserialstr(fmd_hdl_t *hdl, cmd_cpu_t *cp) {
2063325Ssd77468 return (NULL);
2073325Ssd77468 }
2083657Stsien
2095430Ssd77468 /*ARGSUSED*/
2103657Stsien nvlist_t *
cmd_cpu_mkfru(fmd_hdl_t * hdl,char * frustr,char * serialstr,char * partstr)2115430Ssd77468 cmd_cpu_mkfru(fmd_hdl_t *hdl, char *frustr, char *serialstr, char *partstr)
2123657Stsien {
2133657Stsien char *comp;
2143657Stsien nvlist_t *fru, *hcelem;
2153657Stsien
2163657Stsien if (strncmp(frustr, CPU_FRU_FMRI, sizeof (CPU_FRU_FMRI) - 1) != 0)
2173657Stsien return (NULL);
2183657Stsien
2193657Stsien comp = frustr + sizeof (CPU_FRU_FMRI) - 1;
2203657Stsien
2213657Stsien if (nvlist_alloc(&hcelem, NV_UNIQUE_NAME, 0) != 0)
2223657Stsien return (NULL);
2233657Stsien
2243657Stsien if (nvlist_add_string(hcelem, FM_FMRI_HC_NAME,
2253657Stsien FM_FMRI_LEGACY_HC) != 0 ||
2263657Stsien nvlist_add_string(hcelem, FM_FMRI_HC_ID, comp) != 0) {
2273657Stsien nvlist_free(hcelem);
2283657Stsien return (NULL);
2293657Stsien }
2303657Stsien
2313657Stsien if (nvlist_alloc(&fru, NV_UNIQUE_NAME, 0) != 0) {
2323657Stsien nvlist_free(hcelem);
2333657Stsien return (NULL);
2343657Stsien }
2353657Stsien
2363657Stsien if (nvlist_add_uint8(fru, FM_VERSION, FM_HC_SCHEME_VERSION) != 0 ||
2373657Stsien nvlist_add_string(fru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC) != 0 ||
2383657Stsien (partstr != NULL &&
2395430Ssd77468 nvlist_add_string(fru, FM_FMRI_HC_PART, partstr) != 0) ||
2403657Stsien (serialstr != NULL &&
2415430Ssd77468 nvlist_add_string(fru, FM_FMRI_HC_SERIAL_ID,
2425430Ssd77468 serialstr) != 0) ||
2433657Stsien nvlist_add_string(fru, FM_FMRI_HC_ROOT, "") != 0 ||
2443657Stsien nvlist_add_uint32(fru, FM_FMRI_HC_LIST_SZ, 1) != 0 ||
2453657Stsien nvlist_add_nvlist_array(fru, FM_FMRI_HC_LIST, &hcelem, 1) != 0) {
2463657Stsien nvlist_free(hcelem);
2473657Stsien nvlist_free(fru);
2483657Stsien return (NULL);
2493657Stsien }
2503657Stsien
2513657Stsien nvlist_free(hcelem);
2523657Stsien return (fru);
2533657Stsien }
254*8221SSean.Ye@Sun.COM
255*8221SSean.Ye@Sun.COM nvlist_t *
cmd_nvl_create_fault(fmd_hdl_t * hdl,const char * class,uint8_t cert,nvlist_t * asru,nvlist_t * fru,nvlist_t * rsrc)256*8221SSean.Ye@Sun.COM cmd_nvl_create_fault(fmd_hdl_t *hdl, const char *class, uint8_t cert,
257*8221SSean.Ye@Sun.COM nvlist_t *asru, nvlist_t *fru, nvlist_t *rsrc)
258*8221SSean.Ye@Sun.COM {
259*8221SSean.Ye@Sun.COM (void) nvlist_add_nvlist(fru, FM_FMRI_AUTHORITY,
260*8221SSean.Ye@Sun.COM cmd.cmd_auth);
261*8221SSean.Ye@Sun.COM return (fmd_nvl_create_fault(hdl, class, cert, asru, fru, rsrc));
262*8221SSean.Ye@Sun.COM }
263