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 * 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 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 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 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 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