Print this page
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fm/modules/sun4v/cpumem-diagnosis/cmd_memerr_arch.c
+++ new/usr/src/cmd/fm/modules/sun4v/cpumem-diagnosis/cmd_memerr_arch.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * Ereport-handling routines for memory errors
27 27 */
28 28
29 29 #include <cmd_mem.h>
30 30 #include <cmd_dimm.h>
31 31 #include <cmd_bank.h>
32 32 #include <cmd_page.h>
33 33 #include <cmd_cpu.h>
34 34 #include <cmd_branch.h>
35 35 #include <cmd_state.h>
36 36 #include <cmd.h>
37 37 #include <cmd_hc_sun4v.h>
38 38
39 39 #include <assert.h>
40 40 #include <strings.h>
41 41 #include <string.h>
42 42 #include <errno.h>
43 43 #include <unistd.h>
44 44 #include <fm/fmd_api.h>
45 45 #include <sys/fm/ldom.h>
46 46 #include <sys/fm/protocol.h>
47 47
48 48 #include <sys/fm/cpu/UltraSPARC-T1.h>
49 49 #include <sys/mdesc.h>
50 50 #include <sys/async.h>
51 51 #include <sys/errclassify.h>
52 52 #include <sys/niagararegs.h>
53 53 #include <sys/fm/ldom.h>
54 54 #include <ctype.h>
55 55
56 56 #define VF_TS3_FCR 0x000000000000FFFFULL
57 57 #define VF_L2ESYR_C2C 0x8000000000000000ULL
58 58 #define OFFBIT 0xFFFFFFFFFFFC07FFULL
59 59 #define BIT28_32 0x00000001F0000000ULL
60 60 #define BIT13_17 0x000000000003E000ULL
61 61 #define BIT18_19 0x00000000000C0000ULL
62 62 #define BIT11_12 0x0000000000001800ULL
63 63 #define UTS2_CPUS_PER_CHIP 64
64 64 #define FBR_ERROR ".fbr"
65 65 #define DSU_ERROR ".dsu"
66 66 #define FERG_INVALID ".invalid"
67 67 #define DBU_ERROR ".dbu"
68 68
69 69 extern ldom_hdl_t *cpumem_diagnosis_lhp;
70 70
71 71 static fmd_hdl_t *cpumem_hdl = NULL;
72 72
73 73 #define ERR_CLASS(x, y) (strcmp(strrchr(x, '.'), y))
74 74
75 75 static void *
76 76 cpumem_alloc(size_t size)
77 77 {
78 78 assert(cpumem_hdl != NULL);
79 79
80 80 return (fmd_hdl_alloc(cpumem_hdl, size, FMD_SLEEP));
81 81 }
82 82
83 83 static void
84 84 cpumem_free(void *addr, size_t size)
85 85 {
86 86 assert(cpumem_hdl != NULL);
87 87
88 88 fmd_hdl_free(cpumem_hdl, addr, size);
89 89 }
90 90
91 91 /*ARGSUSED*/
92 92 cmd_evdisp_t
93 93 cmd_mem_synd_check(fmd_hdl_t *hdl, uint64_t afar, uint8_t afar_status,
94 94 uint16_t synd, uint8_t synd_status, cmd_cpu_t *cpu)
95 95 {
96 96 /*
97 97 * Niagara writebacks from L2 containing UEs are placed in memory
98 98 * with the poison syndrome NI_DRAM_POISON_SYND_FROM_LDWU.
99 99 * Memory UE ereports showing this syndrome are dropped because they
100 100 * indicate an L2 problem, which should be diagnosed from the
101 101 * corresponding L2 cache ereport.
102 102 */
103 103 switch (cpu->cpu_type) {
104 104 case CPU_ULTRASPARC_T1:
105 105 if (synd == NI_DRAM_POISON_SYND_FROM_LDWU) {
106 106 fmd_hdl_debug(hdl,
107 107 "discarding UE due to magic syndrome %x\n",
108 108 synd);
109 109 return (CMD_EVD_UNUSED);
110 110 }
111 111 break;
112 112 case CPU_ULTRASPARC_T2:
113 113 case CPU_ULTRASPARC_T2plus:
114 114 if (synd == N2_DRAM_POISON_SYND_FROM_LDWU) {
115 115 fmd_hdl_debug(hdl,
116 116 "discarding UE due to magic syndrome %x\n",
117 117 synd);
118 118 return (CMD_EVD_UNUSED);
119 119 }
120 120 break;
121 121 default:
122 122 break;
123 123 }
124 124 return (CMD_EVD_OK);
125 125 }
126 126
127 127 static int
128 128 cpu_present(fmd_hdl_t *hdl, nvlist_t *asru, uint32_t *cpuid)
129 129 {
130 130 nvlist_t *cp_asru;
131 131 uint32_t i;
132 132
133 133 if (nvlist_dup(asru, &cp_asru, 0) != 0) {
134 134 fmd_hdl_debug(hdl, "unable to alloc asru for thread\n");
135 135 return (-1);
136 136 }
137 137
138 138 for (i = *cpuid; i < *cpuid + UTS2_CPUS_PER_CHIP; i++) {
139 139
140 140 (void) nvlist_remove_all(cp_asru, FM_FMRI_CPU_ID);
141 141
142 142 if (nvlist_add_uint32(cp_asru, FM_FMRI_CPU_ID, i) == 0) {
143 143 if (fmd_nvl_fmri_present(hdl, cp_asru) &&
144 144 !fmd_nvl_fmri_unusable(hdl, cp_asru)) {
145 145 nvlist_free(cp_asru);
146 146 *cpuid = i;
147 147 return (0);
148 148 }
149 149 }
150 150 }
151 151 nvlist_free(cp_asru);
152 152 return (-1);
153 153 }
154 154
155 155 /*ARGSUSED*/
156 156 cmd_evdisp_t
157 157 cmd_c2c(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
158 158 cmd_errcl_t clcode)
159 159 {
160 160 uint32_t cpuid;
161 161 nvlist_t *det;
162 162 int rc;
163 163
164 164 (void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &det);
165 165 if (nvlist_lookup_uint32(det, FM_FMRI_CPU_ID, &cpuid) == 0) {
166 166
167 167 /*
168 168 * If the c2c bit is set, the sending cache of the
169 169 * cpu must be faulted instead of the memory.
170 170 * If the detector is chip0, the cache of the chip1
171 171 * is faulted and vice versa.
172 172 */
173 173 if (cpuid < UTS2_CPUS_PER_CHIP)
174 174 cpuid = UTS2_CPUS_PER_CHIP;
175 175 else
176 176 cpuid = 0;
177 177
178 178 rc = cpu_present(hdl, det, &cpuid);
179 179
180 180 if (rc != -1) {
181 181 (void) nvlist_remove(det, FM_FMRI_CPU_ID,
182 182 DATA_TYPE_UINT32);
183 183 if (nvlist_add_uint32(det,
184 184 FM_FMRI_CPU_ID, cpuid) == 0) {
185 185 clcode |= CMD_CPU_LEVEL_CHIP;
186 186 return (cmd_l2u(hdl, ep, nvl, class, clcode));
187 187 }
188 188
189 189 }
190 190 }
191 191 fmd_hdl_debug(hdl, "cmd_c2c: no cpuid discarding C2C error");
192 192 return (CMD_EVD_BAD);
193 193 }
194 194
195 195 /*
196 196 * sun4v's xe_common routine has an extra argument, clcode, compared
197 197 * to routine of same name in sun4u.
198 198 */
199 199
200 200 static cmd_evdisp_t
201 201 xe_common(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
202 202 const char *class, cmd_errcl_t clcode, cmd_xe_handler_f *hdlr)
203 203 {
204 204 uint64_t afar, l2_afar, dram_afar;
205 205 uint64_t l2_afsr, dram_afsr, l2_esyr;
206 206 uint16_t synd;
207 207 uint8_t afar_status, synd_status;
208 208 nvlist_t *rsrc;
209 209 char *typenm;
210 210 uint64_t disp = 0;
211 211 int minorvers = 1;
212 212
213 213 if (nvlist_lookup_uint64(nvl,
214 214 FM_EREPORT_PAYLOAD_NAME_L2_AFSR, &l2_afsr) != 0 &&
215 215 nvlist_lookup_uint64(nvl,
216 216 FM_EREPORT_PAYLOAD_NAME_L2_ESR, &l2_afsr) != 0)
217 217 return (CMD_EVD_BAD);
218 218
219 219 if (nvlist_lookup_uint64(nvl,
220 220 FM_EREPORT_PAYLOAD_NAME_DRAM_AFSR, &dram_afsr) != 0 &&
221 221 nvlist_lookup_uint64(nvl,
222 222 FM_EREPORT_PAYLOAD_NAME_DRAM_ESR, &dram_afsr) != 0)
223 223 return (CMD_EVD_BAD);
224 224
225 225 if (nvlist_lookup_uint64(nvl,
226 226 FM_EREPORT_PAYLOAD_NAME_L2_AFAR, &l2_afar) != 0 &&
227 227 nvlist_lookup_uint64(nvl,
228 228 FM_EREPORT_PAYLOAD_NAME_L2_EAR, &l2_afar) != 0)
229 229 return (CMD_EVD_BAD);
230 230
231 231 if (nvlist_lookup_uint64(nvl,
232 232 FM_EREPORT_PAYLOAD_NAME_DRAM_AFAR, &dram_afar) != 0 &&
233 233 nvlist_lookup_uint64(nvl,
234 234 FM_EREPORT_PAYLOAD_NAME_DRAM_EAR, &dram_afar) != 0)
235 235 return (CMD_EVD_BAD);
236 236
237 237 if (nvlist_lookup_pairs(nvl, 0,
238 238 FM_EREPORT_PAYLOAD_NAME_ERR_TYPE, DATA_TYPE_STRING, &typenm,
239 239 FM_EREPORT_PAYLOAD_NAME_RESOURCE, DATA_TYPE_NVLIST, &rsrc,
240 240 NULL) != 0)
241 241 return (CMD_EVD_BAD);
242 242
243 243 synd = dram_afsr;
244 244
245 245 /*
246 246 * Niagara afar and synd validity.
247 247 * For a given set of error registers, the payload value is valid if
248 248 * no higher priority error status bit is set. See UltraSPARC-T1.h for
249 249 * error status bit values and priority settings. Note that for DAC
250 250 * and DAU, afar value is taken from l2 error registers, syndrome
251 251 * from dram error * registers; for DSC and DSU, both afar and
252 252 * syndrome are taken from dram * error registers. DSU afar and
253 253 * syndrome are always valid because no
254 254 * higher priority error will override.
255 255 */
256 256 switch (clcode) {
257 257 case CMD_ERRCL_DAC:
258 258 afar = l2_afar;
259 259 afar_status = ((l2_afsr & NI_L2AFSR_P10) == 0) ?
260 260 AFLT_STAT_VALID : AFLT_STAT_INVALID;
261 261 synd_status = ((dram_afsr & NI_DMAFSR_P01) == 0) ?
262 262 AFLT_STAT_VALID : AFLT_STAT_INVALID;
263 263 break;
264 264 case CMD_ERRCL_DSC:
265 265 afar = dram_afar;
266 266 afar_status = ((dram_afsr & NI_DMAFSR_P01) == 0) ?
267 267 AFLT_STAT_VALID : AFLT_STAT_INVALID;
268 268 synd_status = afar_status;
269 269 break;
270 270 case CMD_ERRCL_DAU:
271 271 afar = l2_afar;
272 272 afar_status = ((l2_afsr & NI_L2AFSR_P05) == 0) ?
273 273 AFLT_STAT_VALID : AFLT_STAT_INVALID;
274 274 synd_status = AFLT_STAT_VALID;
275 275
276 276 if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_NAME_L2_ESYR,
277 277 &l2_esyr) == 0) {
278 278 if (l2_esyr & VF_L2ESYR_C2C) {
279 279 return (cmd_c2c(hdl, ep, nvl, class, clcode));
280 280 }
281 281 }
282 282 break;
283 283 case CMD_ERRCL_DSU:
284 284 afar = dram_afar;
285 285 afar_status = synd_status = AFLT_STAT_VALID;
286 286 break;
287 287 default:
288 288 fmd_hdl_debug(hdl, "Niagara unrecognized mem error %llx\n",
289 289 clcode);
290 290 return (CMD_EVD_UNUSED);
291 291 }
292 292
293 293 return (hdlr(hdl, ep, nvl, class, afar, afar_status, synd,
294 294 synd_status, cmd_mem_name2type(typenm, minorvers), disp, rsrc));
295 295 }
296 296
297 297
298 298 /*ARGSUSED*/
299 299 cmd_evdisp_t
300 300 cmd_ce(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
301 301 cmd_errcl_t clcode)
302 302 {
303 303 if (strcmp(class, "ereport.cpu.ultraSPARC-T2plus.dsc") == 0)
304 304 return (CMD_EVD_UNUSED); /* drop VF dsc's */
305 305 else
306 306 return (xe_common(hdl, ep, nvl, class, clcode, cmd_ce_common));
307 307 }
308 308
309 309 /*ARGSUSED*/
310 310 cmd_evdisp_t
311 311 cmd_ue_train(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
312 312 cmd_errcl_t clcode)
313 313 {
314 314 cmd_evdisp_t rc, rc1;
315 315
316 316 /*
317 317 * The DAU is cause of the DAU->DCDP/ICDP train:
318 318 * - process the cause of the event.
319 319 * - register the error to the nop event train, so the effected errors
320 320 * (DCDP/ICDP) will be dropped.
321 321 */
322 322 rc = xe_common(hdl, ep, nvl, class, clcode, cmd_ue_common);
323 323
324 324 rc1 = cmd_xxcu_initial(hdl, ep, nvl, class, clcode, CMD_XR_HDLR_NOP);
325 325 if (rc1 != 0)
326 326 fmd_hdl_debug(hdl,
327 327 "Fail to add error (%llx) to the train, rc = %d",
328 328 clcode, rc1);
329 329
330 330 return (rc);
331 331 }
332 332
333 333 /*ARGSUSED*/
334 334 cmd_evdisp_t
335 335 cmd_ue(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
336 336 cmd_errcl_t clcode)
337 337 {
338 338 if (strcmp(class, "ereport.cpu.ultraSPARC-T2plus.dsu") == 0)
339 339 /*
340 340 * VF dsu's need to be treated like branch errors,
341 341 * because we can't localize to a single DIMM or pair of
342 342 * DIMMs given missing/invalid parts of the dram-ear.
343 343 */
344 344 return (cmd_fb(hdl, ep, nvl, class, clcode));
345 345 else
346 346 return (xe_common(hdl, ep, nvl, class, clcode, cmd_ue_common));
347 347 }
348 348
349 349 /*ARGSUSED*/
350 350 cmd_evdisp_t
351 351 cmd_frx(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
352 352 cmd_errcl_t clcode)
353 353 {
354 354 return (CMD_EVD_UNUSED);
355 355 }
356 356
357 357
358 358 /*ARGSUSED*/
359 359 cmd_evdisp_t
360 360 cmd_fb(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
361 361 cmd_errcl_t clcode)
362 362 {
363 363 cmd_branch_t *branch;
364 364 const char *uuid;
365 365 nvlist_t *asru, *det;
366 366 uint64_t ts3_fcr;
367 367
368 368 if (nvlist_lookup_nvlist(nvl, FM_RSRC_RESOURCE, &asru) < 0) {
369 369 CMD_STAT_BUMP(bad_mem_asru);
370 370 return (NULL);
371 371 }
372 372
373 373 if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &det) < 0) {
374 374 CMD_STAT_BUMP(bad_mem_asru);
375 375 return (NULL);
376 376 }
377 377
378 378 if (fmd_nvl_fmri_expand(hdl, det) < 0) {
379 379 fmd_hdl_debug(hdl, "Failed to expand detector");
380 380 return (NULL);
381 381 }
382 382
383 383 branch = cmd_branch_lookup(hdl, asru);
384 384 if (branch == NULL) {
385 385 if ((branch = cmd_branch_create(hdl, asru)) == NULL)
386 386 return (CMD_EVD_UNUSED);
387 387 }
388 388
389 389 if (branch->branch_case.cc_cp != NULL &&
390 390 fmd_case_solved(hdl, branch->branch_case.cc_cp)) {
391 391 fmd_hdl_debug(hdl, "Case solved\n");
392 392 return (CMD_EVD_REDUND);
393 393 }
394 394
395 395 if (branch->branch_case.cc_cp == NULL) {
396 396 branch->branch_case.cc_cp = cmd_case_create(hdl,
397 397 &branch->branch_header, CMD_PTR_BRANCH_CASE, &uuid);
398 398 }
399 399
400 400 if (ERR_CLASS(class, FBR_ERROR) == 0) {
401 401 if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_NAME_TS3_FCR,
402 402 &ts3_fcr) == 0 && (ts3_fcr != VF_TS3_FCR)) {
403 403 fmd_hdl_debug(hdl,
404 404 "Processing fbr with lane failover\n");
405 405 cmd_branch_create_fault(hdl, branch,
406 406 "fault.memory.link-f", det);
407 407
408 408 } else {
409 409 fmd_hdl_debug(hdl, "Adding fbr event to serd engine\n");
410 410 if (branch->branch_case.cc_serdnm == NULL) {
411 411 branch->branch_case.cc_serdnm =
412 412 cmd_mem_serdnm_create(hdl,
413 413 "branch", branch->branch_unum);
414 414
415 415 fmd_serd_create(hdl,
416 416 branch->branch_case.cc_serdnm,
417 417 fmd_prop_get_int32(hdl, "fbr_n"),
418 418 fmd_prop_get_int64(hdl, "fbr_t"));
419 419 }
420 420
421 421 if (fmd_serd_record(hdl,
422 422 branch->branch_case.cc_serdnm, ep) == FMD_B_FALSE)
423 423 return (CMD_EVD_OK); /* engine hasn't fired */
424 424
425 425 fmd_hdl_debug(hdl, "fbr serd fired\n");
426 426
427 427 fmd_case_add_serd(hdl, branch->branch_case.cc_cp,
428 428 branch->branch_case.cc_serdnm);
429 429
430 430 cmd_branch_create_fault(hdl, branch,
431 431 "fault.memory.link-c", det);
432 432 }
433 433 } else if (ERR_CLASS(class, DSU_ERROR) == 0) {
434 434 fmd_hdl_debug(hdl, "Processing dsu event");
435 435 cmd_branch_create_fault(hdl, branch, "fault.memory.bank", det);
436 436 } else {
437 437 fmd_hdl_debug(hdl, "Processing fbu event");
438 438 cmd_branch_create_fault(hdl, branch, "fault.memory.link-u",
439 439 det);
440 440 }
441 441
442 442 branch->branch_flags |= CMD_MEM_F_FAULTING;
443 443
444 444 if (branch->branch_case.cc_serdnm != NULL) {
445 445 fmd_serd_destroy(hdl, branch->branch_case.cc_serdnm);
446 446 fmd_hdl_strfree(hdl, branch->branch_case.cc_serdnm);
447 447 branch->branch_case.cc_serdnm = NULL;
448 448 }
449 449
450 450 fmd_case_add_ereport(hdl, branch->branch_case.cc_cp, ep);
451 451 fmd_case_solve(hdl, branch->branch_case.cc_cp);
452 452 cmd_branch_dirty(hdl, branch);
453 453
454 454 return (CMD_EVD_OK);
455 455 }
456 456
457 457 /*ARGSUSED*/
458 458 cmd_evdisp_t
459 459 cmd_fb_train(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
460 460 cmd_errcl_t clcode)
461 461 {
462 462 cmd_evdisp_t rc, rc1;
463 463
464 464 /*
465 465 * The FBU is cause of the FBU->DCDP/ICDP train:
466 466 * - process the cause of the event.
467 467 * - register the error to the nop event train, so the effected errors
468 468 * (DCDP/ICDP) will be dropped.
469 469 */
470 470 rc = cmd_fb(hdl, ep, nvl, class, clcode);
471 471
472 472 rc1 = cmd_xxcu_initial(hdl, ep, nvl, class, clcode, CMD_XR_HDLR_NOP);
473 473 if (rc1 != 0)
474 474 fmd_hdl_debug(hdl,
475 475 "Fail to add error (%llx) to the train, rc = %d",
476 476 clcode, rc1);
477 477
478 478 return (rc);
479 479 }
480 480
481 481
482 482 /*ARGSUSED*/
483 483 cmd_evdisp_t
484 484 cmd_fw_defect(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
485 485 cmd_errcl_t clcode)
486 486 {
487 487 const char *fltclass = NULL;
488 488 nvlist_t *rsc = NULL;
489 489 int solve = 0;
490 490
491 491 if ((rsc = init_mb(hdl)) == NULL)
492 492 return (CMD_EVD_UNUSED);
493 493
494 494 if (ERR_CLASS(class, FERG_INVALID) == 0) {
495 495 fltclass = "defect.fw.generic-sparc.erpt-gen";
496 496 } else if (ERR_CLASS(class, DBU_ERROR) == 0) {
497 497 cmd_evdisp_t rc;
498 498 fltclass = "defect.fw.generic-sparc.addr-oob";
499 499 /*
500 500 * add dbu to nop error train
501 501 */
502 502 rc = cmd_xxcu_initial(hdl, ep, nvl, class, clcode,
503 503 CMD_XR_HDLR_NOP);
504 504 if (rc != 0)
505 505 fmd_hdl_debug(hdl,
506 506 "Failed to add error (%llx) to the train, rc = %d",
507 507 clcode, rc);
508 508 } else {
509 509 fmd_hdl_debug(hdl, "Unexpected fw defect event %s", class);
510 510 }
511 511
512 512 if (fltclass) {
513 513 fmd_case_t *cp = NULL;
514 514 nvlist_t *fault = NULL;
515 515
516 516 fault = fmd_nvl_create_fault(hdl, fltclass, 100, NULL,
↓ open down ↓ |
516 lines elided |
↑ open up ↑ |
517 517 NULL, rsc);
518 518 if (fault != NULL) {
519 519 cp = fmd_case_open(hdl, NULL);
520 520 fmd_case_add_ereport(hdl, cp, ep);
521 521 fmd_case_add_suspect(hdl, cp, fault);
522 522 fmd_case_solve(hdl, cp);
523 523 solve = 1;
524 524 }
525 525 }
526 526
527 - if (rsc)
528 - nvlist_free(rsc);
527 + nvlist_free(rsc);
529 528
530 529 return (solve ? CMD_EVD_OK : CMD_EVD_UNUSED);
531 530 }
532 531
533 532 void
534 533 cmd_branch_close(fmd_hdl_t *hdl, void *arg)
535 534 {
536 535 cmd_branch_destroy(hdl, arg);
537 536 }
538 537
539 538
540 539 /*ARGSUSED*/
541 540 ulong_t
542 541 cmd_mem_get_phys_pages(fmd_hdl_t *hdl)
543 542 {
544 543 /*
545 544 * Compute and return the total physical memory in pages from the
546 545 * MD/PRI.
547 546 * Cache its value.
548 547 */
549 548 static ulong_t npage = 0;
550 549 md_t *mdp;
551 550 mde_cookie_t *listp;
552 551 uint64_t bmem, physmem = 0;
553 552 ssize_t bufsiz = 0;
554 553 uint64_t *bufp;
555 554 int num_nodes, nmblocks, i;
556 555
557 556 if (npage > 0) {
558 557 return (npage);
559 558 }
560 559
561 560 if (cpumem_hdl == NULL) {
562 561 cpumem_hdl = hdl;
563 562 }
564 563
565 564 if ((bufsiz = ldom_get_core_md(cpumem_diagnosis_lhp, &bufp)) <= 0) {
566 565 return (0);
567 566 }
568 567 if ((mdp = md_init_intern(bufp, cpumem_alloc, cpumem_free)) == NULL ||
569 568 (num_nodes = md_node_count(mdp)) <= 0) {
570 569 cpumem_free(bufp, (size_t)bufsiz);
571 570 return (0);
572 571 }
573 572
574 573 listp = (mde_cookie_t *)cpumem_alloc(sizeof (mde_cookie_t) *
575 574 num_nodes);
576 575 nmblocks = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE,
577 576 md_find_name(mdp, "mblock"),
578 577 md_find_name(mdp, "fwd"), listp);
579 578 for (i = 0; i < nmblocks; i++) {
580 579 if (md_get_prop_val(mdp, listp[i], "size", &bmem) < 0) {
581 580 physmem = 0;
582 581 break;
583 582 }
584 583 physmem += bmem;
585 584 }
586 585 npage = (ulong_t)(physmem / cmd.cmd_pagesize);
587 586
588 587 cpumem_free(listp, sizeof (mde_cookie_t) * num_nodes);
589 588 cpumem_free(bufp, (size_t)bufsiz);
590 589 (void) md_fini(mdp);
591 590
592 591 return (npage);
593 592 }
594 593
595 594 static int galois_mul[16][16] = {
596 595 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
597 596 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 0 */
598 597 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, /* 1 */
599 598 { 0, 2, 4, 6, 8, 10, 12, 14, 3, 1, 7, 5, 11, 9, 15, 13}, /* 2 */
600 599 { 0, 3, 6, 5, 12, 15, 10, 9, 11, 8, 13, 14, 7, 4, 1, 2}, /* 3 */
601 600 { 0, 4, 8, 12, 3, 7, 11, 15, 6, 2, 14, 10, 5, 1, 13, 9}, /* 4 */
602 601 { 0, 5, 10, 15, 7, 2, 13, 8, 14, 11, 4, 1, 9, 12, 3, 6}, /* 5 */
603 602 { 0, 6, 12, 10, 11, 13, 7, 1, 5, 3, 9, 15, 14, 8, 2, 4}, /* 6 */
604 603 { 0, 7, 14, 9, 15, 8, 1, 6, 13, 10, 3, 4, 2, 5, 12, 11}, /* 7 */
605 604 { 0, 8, 3, 11, 6, 14, 5, 13, 12, 4, 15, 7, 10, 2, 9, 1}, /* 8 */
606 605 { 0, 9, 1, 8, 2, 11, 3, 10, 4, 13, 5, 12, 6, 15, 7, 14}, /* 9 */
607 606 { 0, 10, 7, 13, 14, 4, 9, 3, 15, 5, 8, 2, 1, 11, 6, 12}, /* A */
608 607 { 0, 11, 5, 14, 10, 1, 15, 4, 7, 12, 2, 9, 13, 6, 8, 3}, /* B */
609 608 { 0, 12, 11, 7, 5, 9, 14, 2, 10, 6, 1, 13, 15, 3, 4, 8}, /* C */
610 609 { 0, 13, 9, 4, 1, 12, 8, 5, 2, 15, 11, 6, 3, 14, 10, 7}, /* D */
611 610 { 0, 14, 15, 1, 13, 3, 2, 12, 9, 7, 6, 8, 4, 10, 11, 5}, /* E */
612 611 { 0, 15, 13, 2, 9, 6, 4, 11, 1, 14, 12, 3, 8, 7, 5, 10} /* F */
613 612 };
614 613
615 614 static int
616 615 galois_div(int num, int denom) {
617 616 int i;
618 617
619 618 for (i = 0; i < 16; i++) {
620 619 if (galois_mul[denom][i] == num)
621 620 return (i);
622 621 }
623 622 return (-1);
624 623 }
625 624
626 625 /*
627 626 * Data nibbles N0-N31 => 0-31
628 627 * check nibbles C0-3 => 32-35
629 628 */
630 629
631 630 int
632 631 cmd_synd2upos(uint16_t syndrome) {
633 632
634 633 uint16_t s0, s1, s2, s3;
635 634
636 635 if (syndrome == 0)
637 636 return (-1); /* clean syndrome, not a CE */
638 637
639 638 s0 = syndrome & 0xF;
640 639 s1 = (syndrome >> 4) & 0xF;
641 640 s2 = (syndrome >> 8) & 0xF;
642 641 s3 = (syndrome >> 12) & 0xF;
643 642
644 643 if (s3 == 0) {
645 644 if (s2 == 0 && s1 == 0)
646 645 return (32); /* 0 0 0 e => C0 */
647 646 if (s2 == 0 && s0 == 0)
648 647 return (33); /* 0 0 e 0 => C1 */
649 648 if (s1 == 0 && s0 == 0)
650 649 return (34); /* 0 e 0 0 => C2 */
651 650 if (s2 == s1 && s1 == s0)
652 651 return (31); /* 0 d d d => N31 */
653 652 return (-1); /* multibit error */
654 653 } else if (s2 == 0) {
655 654 if (s1 == 0 && s0 == 0)
656 655 return (35); /* e 0 0 0 => C4 */
657 656 if (s1 == 0 || s0 == 0)
658 657 return (-1); /* not a 0 b c */
659 658 if (s3 != galois_div(galois_mul[s1][s1], s0))
660 659 return (-1); /* check nibble not valid */
661 660 return (galois_div(s0, s1) - 1); /* N0 - N14 */
662 661 } else if (s1 == 0) {
663 662 if (s2 == 0 || s0 == 0)
664 663 return (-1); /* not a b 0 c */
665 664 if (s3 != galois_div(galois_mul[s2][s2], s0))
666 665 return (-1); /* check nibble not valid */
667 666 return (galois_div(s0, s2) + 14); /* N15 - N29 */
668 667 } else if (s0 == 0) {
669 668 if (s3 == s2 && s2 == s1)
670 669 return (30); /* d d d 0 => N30 */
671 670 return (-1);
672 671 } else return (-1);
673 672 }
674 673
675 674 nvlist_t *
676 675 cmd_mem2hc(fmd_hdl_t *hdl, nvlist_t *mem_fmri) {
677 676
678 677 char **snp;
679 678 uint_t n;
680 679
681 680 if (nvlist_lookup_string_array(mem_fmri, FM_FMRI_HC_SERIAL_ID,
682 681 &snp, &n) != 0)
683 682 return (NULL); /* doesn't have serial id */
684 683
685 684 return (cmd_find_dimm_by_sn(hdl, FM_FMRI_SCHEME_HC, *snp));
686 685 }
687 686
688 687 /*
689 688 * formula to convert an unhashed address to hashed address
690 689 * PA[17:11] = (PA[32:28] xor PA[17:13]) :: ((PA[19:18] xor PA[12:11])
691 690 */
692 691 void
693 692 cmd_to_hashed_addr(uint64_t *addr, uint64_t afar, const char *class)
694 693 {
695 694
696 695 if (strstr(class, "ultraSPARC-T1") != NULL)
697 696 *addr = afar;
698 697 else {
699 698 *addr = (afar & OFFBIT) |
700 699 ((afar & BIT28_32) >> 15) ^ (afar & BIT13_17) |
701 700 ((afar & BIT18_19) >> 7) ^ (afar & BIT11_12);
702 701 }
703 702 }
704 703
705 704 int
706 705 cmd_same_datapath_dimms(cmd_dimm_t *d1, cmd_dimm_t *d2)
707 706 {
708 707 char *p, *q;
709 708
710 709 p = strstr(d1->dimm_unum, "CMP");
711 710 q = strstr(d2->dimm_unum, "CMP");
712 711 if (p != NULL && q != NULL) {
713 712 if (strncmp(p, q, 4) == 0)
714 713 return (1);
715 714 }
716 715 return (0);
717 716 }
718 717
719 718 /*
720 719 * fault the FRU of the common CMP
721 720 */
722 721 /*ARGSUSED*/
723 722 void
724 723 cmd_gen_datapath_fault(fmd_hdl_t *hdl, cmd_dimm_t *d1, cmd_dimm_t *d2,
725 724 uint16_t upos, nvlist_t *det)
726 725 {
727 726 fmd_case_t *cp;
728 727 char *frustr;
729 728 nvlist_t *rsrc, *fltlist;
730 729 char *s;
731 730 char const *str1, *str2;
732 731 uint_t len, i;
733 732
734 733 s = strstr(d1->dimm_unum, "CMP");
735 734 if (s == NULL)
736 735 return;
737 736
738 737 frustr = fmd_hdl_zalloc(hdl, strlen(d1->dimm_unum), FMD_SLEEP);
739 738 len = strlen(d1->dimm_unum) - strlen(s);
740 739
741 740 if (strncmp(d1->dimm_unum, d2->dimm_unum, len) != 0) {
742 741 for (i = 0, str1 = d1->dimm_unum, str2 = d2->dimm_unum;
743 742 *str1 == *str2 && i <= len;
744 743 str1++, str2++, i++)
745 744 ;
746 745 len = i;
747 746 }
748 747
749 748 (void) strncpy(frustr, d1->dimm_unum, len);
750 749
751 750 rsrc = cmd_mkboard_fru(hdl, frustr, NULL, NULL);
752 751
753 752 fmd_hdl_free(hdl, frustr, strlen(d1->dimm_unum));
754 753
755 754 if (rsrc == NULL)
756 755 return;
757 756
758 757 (void) nvlist_add_nvlist(rsrc, FM_FMRI_AUTHORITY, cmd.cmd_auth);
759 758
760 759 cp = fmd_case_open(hdl, NULL);
761 760
762 761 fltlist = fmd_nvl_create_fault(hdl, "fault.memory.datapath", 100,
763 762 rsrc, NULL, rsrc);
764 763
765 764 fmd_case_add_suspect(hdl, cp, fltlist);
766 765 fmd_case_solve(hdl, cp);
767 766
768 767 nvlist_free(rsrc);
769 768 }
↓ open down ↓ |
231 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX