4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <sys/param.h>
36 #include <fm/fmd_api.h>
37 #include <sys/fm/protocol.h>
38 #include <sys/async.h>
40 #define IOD_STAT_BUMP(name) iod.iod_stats->name.fmds_value.ui64++
45 * This diagnosis engine consumes the Psycho based IO UEs and CEs
46 * which are generated due to DMA Reads or Writes.
48 * When a UE is received it will generate the appropriate fault
49 * (defect.ultraSPARC-II.memory.nodiag). This is because we do not plan
50 * to currently add greater diagnosis capabilities for USII systems.
52 * When a CE is received we allow the legacy in kernel SERD do it's job
53 * and we just bump a counter here. The legacy SERD algorithm will print
54 * out a message and retire pages when the SERD threshold is reached.
57 static void iod_recv(fmd_hdl_t
*, fmd_event_t
*, nvlist_t
*, const char *);
59 typedef struct iod_stat
{
60 fmd_stat_t ue
; /* # of UEs received */
61 fmd_stat_t ce
; /* # of CEs received */
65 iod_stat_t
*iod_stats
; /* Module statistics */
68 static const fmd_hdl_ops_t fmd_ops
= {
69 iod_recv
, /* fmdo_recv */
70 NULL
, /* fmdo_timeout */
71 NULL
, /* fmdo_close */
72 NULL
, /* fmdo_stats */
76 static const fmd_hdl_info_t fmd_info
= {
77 "UltraSPARC-II I/O Diagnosis", IOD_VERSION
, &fmd_ops
, NULL
80 static const iod_stat_t iod_stat
= {
81 { "ue", FMD_TYPE_UINT64
, "number of received IO UEs" },
82 { "ce", FMD_TYPE_UINT64
, "number of received IO CEs" }
89 iod_recv(fmd_hdl_t
*hdl
, fmd_event_t
*ep
, nvlist_t
*nvl
, const char *class)
93 char flt
[] = "defect.ultraSPARC-II.memory.nodiag";
95 if (fmd_nvl_class_match(hdl
, nvl
, "*ue")) {
97 cp
= fmd_case_open(hdl
, NULL
);
98 fault
= fmd_nvl_create_fault(hdl
, flt
, 100, NULL
, NULL
, NULL
);
99 fmd_case_add_ereport(hdl
, cp
, ep
);
100 fmd_case_add_suspect(hdl
, cp
, fault
);
101 fmd_case_solve(hdl
, cp
);
102 } else if (fmd_nvl_class_match(hdl
, nvl
, "*ce")) {
108 iod_cpu_check_support(void)
115 if ((kc
= kstat_open()) == NULL
)
118 for (ksp
= kc
->kc_chain
; ksp
!= NULL
; ksp
= ksp
->ks_next
) {
119 if (strcmp(ksp
->ks_module
, "cpu_info") != 0)
122 if (kstat_read(kc
, ksp
, NULL
) == -1) {
123 (void) kstat_close(kc
);
127 for (kn
= ksp
->ks_data
, i
= 0; i
< ksp
->ks_ndata
; i
++, kn
++) {
128 if (strcmp(kn
->name
, "implementation") != 0)
131 if (strncmp(KSTAT_NAMED_STR_PTR(kn
), "UltraSPARC-II",
132 sizeof ("UltraSPARC-II") - 1) == 0 &&
133 strncmp(KSTAT_NAMED_STR_PTR(kn
), "UltraSPARC-III",
134 sizeof ("UltraSPARC-III") - 1) != 0) {
135 (void) kstat_close(kc
);
141 (void) kstat_close(kc
);
146 _fmd_init(fmd_hdl_t
*hdl
)
148 if (fmd_hdl_register(hdl
, FMD_API_VERSION
, &fmd_info
) != 0)
149 return; /* error in configuration file or fmd_info */
151 if (!iod_cpu_check_support()) {
152 fmd_hdl_debug(hdl
, "no supported CPUs found");
153 fmd_hdl_unregister(hdl
);
157 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.drue");
158 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.s-drue");
159 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.dwue");
160 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.s-dwue");
161 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.drce");
162 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.s-drce");
163 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.dwce");
164 fmd_hdl_subscribe(hdl
, "ereport.io.psy.ecc.s-dwce");
166 bzero(&iod
, sizeof (iod_t
));
168 iod
.iod_stats
= (iod_stat_t
*)fmd_stat_create(hdl
, FMD_STAT_NOALLOC
,
169 sizeof (iod_stat
) / sizeof (fmd_stat_t
), (fmd_stat_t
*)&iod_stat
);