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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * Case management and saved state restoration
29 */
30
31 #include <cmd_state.h>
32 #include <cmd_cpu.h>
33 #include <cmd_mem.h>
34 #include <cmd_page.h>
35 #include <cmd_dimm.h>
36 #ifdef sun4u
37 #include <cmd_dp.h>
38 #include <cmd_dp_page.h>
39 #include <cmd_Lxcache.h>
40 #endif
41 #include <cmd_bank.h>
42 #include <cmd.h>
43 #ifdef sun4v
44 #include <cmd_branch.h>
45 #endif
46
47 #include <string.h>
48 #include <fm/fmd_api.h>
49
50 #ifdef sun4u
51 #include <cmd_opl.h>
52 #endif
53
54 /* Must be in sync with cmd_ptrsubtype_t */
55 static cmd_case_closer_f *const cmd_case_closers[] = {
56 NULL,
57 cmd_cpuerr_close, /* CMD_PTR_CPU_ICACHE */
58 cmd_cpuerr_close, /* CMD_PTR_CPU_DCACHE */
59 cmd_cpuerr_close, /* CMD_PTR_CPU_PCACHE */
60 cmd_cpuerr_close, /* CMD_PTR_CPU_ITLB */
61 cmd_cpuerr_close, /* CMD_PTR_CPU_DTLB */
62 cmd_cpuerr_close, /* CMD_PTR_CPU_L2DATA */
63 cmd_cpuerr_close, /* CMD_PTR_CPU_L2DATA_UERETRY */
64 cmd_cpuerr_close, /* CMD_PTR_CPU_L2TAG */
65 cmd_cpuerr_close, /* CMD_PTR_CPU_L3DATA */
66 cmd_cpuerr_close, /* CMD_PTR_CPU_L3DATA_UERETRY */
67 cmd_cpuerr_close, /* CMD_PTR_CPU_L3TAG */
68 cmd_dimm_close, /* CMD_PTR_DIMM_CASE */
69 cmd_bank_close, /* CMD_PTR_BANK_CASE */
70 cmd_page_close, /* CMD_PTR_PAGE_CASE */
71 cmd_cpuerr_close, /* CMD_PTR_CPU_FPU */
72 NULL, /* CMD_PTR_CPU_XR_RETRY */
73 cmd_cpuerr_close, /* CMD_PTR_CPU_IREG */
74 cmd_cpuerr_close, /* CMD_PTR_CPU_FREG */
75 cmd_cpuerr_close, /* CMD_PTR_CPU_MAU */
76 cmd_cpuerr_close, /* CMD_PTR_CPU_L2CTL */
77 #ifdef sun4u
78 cmd_dp_close, /* CMD_PTR_DP_CASE */
79 #else
80 NULL, /* CMD_PTR_DP_CASE */
81 #endif
82 NULL, /* CMD_PTR_DP_PAGE_DEFER */
83 cmd_cpuerr_close, /* CMD_PTR_CPU_INV_SFSR */
84 cmd_cpuerr_close, /* CMD_PTR_CPU_UE_DET_CPU */
85 cmd_cpuerr_close, /* CMD_PTR_CPU_UE_DET_IO */
86 cmd_cpuerr_close, /* CMD_PTR_CPU_MTLB */
87 cmd_cpuerr_close, /* CMD_PTR_CPU_TLBP */
88 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_INV_URG */
89 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_CRE */
90 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_TSB_CTX */
91 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_TSBP */
92 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_PSTATE */
93 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_TSTATE */
94 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_IUG_F */
95 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_IUG_R */
96 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_SDC */
97 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_WDT */
98 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_DTLB */
99 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_ITLB */
100 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_CORE_ERR */
101 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_DAE */
102 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_IAE */
103 cmd_cpuerr_close, /* CMD_PTR_CPU_UGESR_UGE */
104 cmd_cpuerr_close, /* CMD_PTR_CPU_MISC_REGS */
105 cmd_cpuerr_close, /* CMD_PTR_CPU_LFU */
106 #ifdef sun4v
107 cmd_branch_close /* CMD_PTR_BRANCH_CASE */
108 #else
109 NULL,
110 cmd_Lxcache_close, /* CMD_PTR_CACHE_CASE */
111
112 #endif
113 };
114
115 fmd_case_t *
cmd_case_create(fmd_hdl_t * hdl,cmd_header_t * hdr,cmd_ptrsubtype_t ptrsubtype,const char ** uuidp)116 cmd_case_create(fmd_hdl_t *hdl, cmd_header_t *hdr, cmd_ptrsubtype_t ptrsubtype,
117 const char **uuidp)
118 {
119 cmd_case_ptr_t ptr;
120 cmd_case_closer_t *cl;
121 fmd_case_t *cp;
122
123 cl = fmd_hdl_alloc(hdl, sizeof (cmd_case_closer_t), FMD_SLEEP);
124 cl->cl_func = cmd_case_closers[ptrsubtype];
125 cl->cl_arg = hdr;
126
127 cp = fmd_case_open(hdl, cl);
128
129 ptr.ptr_type = hdr->hdr_nodetype;
130 ptr.ptr_subtype = ptrsubtype;
131 (void) strcpy(ptr.ptr_name, hdr->hdr_bufname);
132
133 *uuidp = fmd_case_uuid(hdl, cp);
134 fmd_buf_write(hdl, cp, *uuidp, &ptr, sizeof (cmd_case_ptr_t));
135
136 return (cp);
137 }
138
139 void
cmd_case_redirect(fmd_hdl_t * hdl,fmd_case_t * cp,cmd_ptrsubtype_t newsubtype)140 cmd_case_redirect(fmd_hdl_t *hdl, fmd_case_t *cp, cmd_ptrsubtype_t newsubtype)
141 {
142 const char *uuid = fmd_case_uuid(hdl, cp);
143 cmd_case_ptr_t ptr;
144
145 fmd_buf_read(hdl, cp, uuid, &ptr, sizeof (cmd_case_ptr_t));
146 fmd_hdl_debug(hdl, "redirecting case %s from %d to %d\n", uuid,
147 ptr.ptr_subtype, newsubtype);
148 ptr.ptr_subtype = newsubtype;
149 fmd_buf_write(hdl, cp, uuid, &ptr, sizeof (cmd_case_ptr_t));
150 }
151
152 void
cmd_case_fini(fmd_hdl_t * hdl,fmd_case_t * cp,int close)153 cmd_case_fini(fmd_hdl_t *hdl, fmd_case_t *cp, int close)
154 {
155 const char *uuid = fmd_case_uuid(hdl, cp);
156 cmd_case_closer_t *cl = fmd_case_getspecific(hdl, cp);
157
158 if (close) {
159 fmd_hdl_debug(hdl, "closing case %s\n", uuid);
160
161 if (fmd_serd_exists(hdl, uuid))
162 fmd_serd_destroy(hdl, uuid);
163
164 if (fmd_buf_size(hdl, cp, uuid) != 0)
165 fmd_buf_destroy(hdl, cp, uuid);
166
167 fmd_case_setspecific(hdl, cp, NULL);
168 fmd_case_close(hdl, cp);
169 }
170
171 if (cl != NULL)
172 fmd_hdl_free(hdl, cl, sizeof (cmd_case_closer_t));
173 }
174
175 /* Must be in sync with cmd_nodetype_t */
176 static cmd_case_restorer_f *const cmd_case_restorers[] = {
177 NULL,
178 cmd_cpu_restore, /* CMD_NT_CPU */
179 cmd_dimm_restore, /* CMD_NT_DIMM */
180 cmd_bank_restore, /* CMD_NT_BANK */
181 cmd_page_restore, /* CMD_NT_PAGE */
182 #ifdef sun4u
183 cmd_dp_restore, /* CMD_NT_DP */
184 cmd_Lxcache_restore, /* CMD_NT_CACHE */
185 #endif
186 #ifdef sun4v
187 cmd_branch_restore /* CMD_NT_BRANCH */
188 #endif
189 };
190
191 int
cmd_state_restore(fmd_hdl_t * hdl)192 cmd_state_restore(fmd_hdl_t *hdl)
193 {
194 fmd_case_t *cp = NULL;
195
196 while ((cp = fmd_case_next(hdl, cp)) != NULL) {
197 const char *uuid = fmd_case_uuid(hdl, cp);
198 cmd_case_closer_t *cl;
199 cmd_case_ptr_t ptr;
200 void *thing;
201 size_t sz;
202
203 if ((sz = fmd_buf_size(hdl, cp, uuid)) == 0)
204 continue;
205 else if (sz != sizeof (cmd_case_ptr_t))
206 return (cmd_set_errno(EINVAL));
207
208 fmd_buf_read(hdl, cp, fmd_case_uuid(hdl, cp), &ptr,
209 sizeof (cmd_case_ptr_t));
210
211 if (ptr.ptr_type == 0 || ptr.ptr_type >=
212 sizeof (cmd_case_restorers) /
213 sizeof (cmd_case_restorer_f *))
214 return (cmd_set_errno(EINVAL));
215
216 if ((thing = cmd_case_restorers[ptr.ptr_type](hdl,
217 cp, &ptr)) == NULL) {
218 fmd_hdl_debug(hdl, "Unable to restore case %s\n", uuid);
219 continue;
220 }
221
222 cl = fmd_hdl_alloc(hdl, sizeof (cmd_case_closer_t), FMD_SLEEP);
223 cl->cl_func = cmd_case_closers[ptr.ptr_subtype];
224 cl->cl_arg = thing;
225 fmd_case_setspecific(hdl, cp, cl);
226 }
227
228 cmd_trw_restore(hdl);
229
230 cmd_cpu_validate(hdl);
231 cmd_bank_validate(hdl);
232 cmd_dimm_validate(hdl);
233 #ifdef sun4u
234 /*
235 * cmd_dp_page_validate() must be done before cmd_dp_validate()
236 * and cmd_page_validate()
237 */
238 cmd_dp_page_validate(hdl);
239 cmd_dp_validate(hdl);
240 #endif
241 cmd_page_validate(hdl);
242 #ifdef sun4v
243 cmd_branch_validate(hdl);
244 #endif
245
246 return (0);
247 }
248
249 void
cmd_case_restore(fmd_hdl_t * hdl,cmd_case_t * cc,fmd_case_t * cp,char * serdnm)250 cmd_case_restore(fmd_hdl_t *hdl, cmd_case_t *cc, fmd_case_t *cp, char *serdnm)
251 {
252 if (!fmd_serd_exists(hdl, serdnm)) {
253 fmd_hdl_strfree(hdl, serdnm);
254 serdnm = NULL;
255 }
256
257 cc->cc_cp = cp;
258 cc->cc_serdnm = serdnm;
259 }
260